From 9540a0d34a5f2c1cd17c3c720400a11a38271180 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 9 Oct 2020 18:35:16 +0200 Subject: [PATCH 001/185] minor changes in ulsim --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 71132b64c5..68ef855814 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1488,7 +1488,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, corr_tmp += corr_re*corr_re + corr_im*corr_im; } // aa loop }// group loop - + LOG_D(PHY,"cw %d, metric %f dB\n",cw,10*log10(corr_tmp)); if (corr_tmp > corr) { corr = corr_tmp; cw_ML=cw; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 9dd6d61557..c6afbbc513 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -754,6 +754,9 @@ int main(int argc, char **argv) slot_offset, ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i], ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]); + + mod_order = nr_get_Qm_ul(Imcs, 0); + code_rate = nr_get_code_rate_ul(Imcs, 0); } for (SNR = snr0; SNR < snr1; SNR += snr_step) { From d26d60300ed6bf9ab6aaa072ebf09b10cc94bdfa Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 22 Feb 2021 12:26:42 +0100 Subject: [PATCH 002/185] added a PRB-based channel estimation. It averages the 4/6 DMRS LS channel estimates and uses a single value per PRB. Improves performance of high MCS PHY_VARS_NR_UE now has a flag fd_lin_interpolation which turns this on/off. By default it uses the "new" method. --- .../nr_dl_channel_estimation.c | 499 +++++++++++------- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 2 +- openair1/PHY/defs_nr_UE.h | 3 + openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- 4 files changed, 299 insertions(+), 207 deletions(-) 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 6cb0a612e9..e869febe27 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -452,19 +452,19 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, } if( dmrss == 2) // update time statistics for last PBCH symbol - { - // do ifft of channel estimate - for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) - for (p=0; pframe_parms.nb_antenna_ports_gNB; p++) { - if (ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx]) - { - LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d ch_offset %d\n", Ns, proc->thread_id, symbol, ch_offset); - idft(idftsizeidx, - (int16_t*) &ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx][ch_offset], - (int16_t*) ue->pbch_vars[eNB_offset]->dl_ch_estimates_time[(p<<1)+aarx],1); - } - } - } + { + // do ifft of channel estimate + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) + for (p=0; pframe_parms.nb_antenna_ports_gNB; p++) { + if (ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx]) + { + LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d ch_offset %d\n", Ns, proc->thread_id, symbol, ch_offset); + idft(idftsizeidx, + (int16_t*) &ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx][ch_offset], + (int16_t*) ue->pbch_vars[eNB_offset]->dl_ch_estimates_time[(p<<1)+aarx],1); + } + } + } //} @@ -536,31 +536,88 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, printf("dl_ch addr %p\n",dl_ch); #endif // if ((ue->frame_parms.N_RB_DL&1)==0) { - // Treat first 2 pilots specially (left edge) + // Treat first 2 pilots specially (left edge) + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); +#ifdef DEBUG_PDCCH + printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); + printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); +#endif + multadd_real_vector_complex_scalar(fl, + ch, + dl_ch, + 16); + pil+=2; + rxF+=8; + //for (int i= 0; i<8; i++) + //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); + + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); +#ifdef DEBUG_PDCCH + printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif + multadd_real_vector_complex_scalar(fm, + ch, + dl_ch, + 16); + pil+=2; + rxF+=8; + + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + +#ifdef DEBUG_PDCCH + printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); +#endif + + multadd_real_vector_complex_scalar(fr, + ch, + dl_ch, + 16); + +#ifdef DEBUG_PDCCH + for (int m =0; m<12; m++) + printf("data : dl_ch -> (%d,%d)\n",dl_ch[0+2*m],dl_ch[1+2*m]); +#endif + pil+=2; + rxF+=8; + dl_ch+=24; + k+=12; + + + + for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt+=3) { + + if (k >= ue->frame_parms.ofdm_symbol_size){ + k-=ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];} + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDCCH - printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); - printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fl, - ch, - dl_ch, - 16); + ch, + dl_ch, + 16); + + //for (int i= 0; i<8; i++) + // printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); + pil+=2; rxF+=8; - //for (int i= 0; i<8; i++) - //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDCCH - printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fm, - ch, - dl_ch, - 16); + ch, + dl_ch, + 16); pil+=2; rxF+=8; @@ -568,79 +625,22 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDCCH - printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fr, - ch, - dl_ch, - 16); - -#ifdef DEBUG_PDCCH - for (int m =0; m<12; m++) - printf("data : dl_ch -> (%d,%d)\n",dl_ch[0+2*m],dl_ch[1+2*m]); -#endif + ch, + dl_ch, + 16); pil+=2; rxF+=8; dl_ch+=24; k+=12; - - - for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt+=3) { - - if (k >= ue->frame_parms.ofdm_symbol_size){ - k-=ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+1)];} - - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); -#ifdef DEBUG_PDCCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); -#endif - multadd_real_vector_complex_scalar(fl, - ch, - dl_ch, - 16); - - //for (int i= 0; i<8; i++) - // printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); - - pil+=2; - rxF+=8; - - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); -#ifdef DEBUG_PDCCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); -#endif - multadd_real_vector_complex_scalar(fm, - ch, - dl_ch, - 16); - pil+=2; - rxF+=8; - - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - -#ifdef DEBUG_PDCCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); -#endif - - multadd_real_vector_complex_scalar(fr, - ch, - dl_ch, - 16); - pil+=2; - rxF+=8; - dl_ch+=24; - k+=12; - - } + } - //} + //} } @@ -662,7 +662,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short k; unsigned int pilot_cnt; int16_t ch_l[2],ch_r[2],ch[2],*pil,*rxF,*dl_ch; - int16_t *fl,*fm,*fr,*fml,*fmr,*fmm,*fdcl,*fdcr,*fdclh,*fdcrh, *frl, *frr; + int16_t *fl=NULL,*fm=NULL,*fr=NULL,*fml=NULL,*fmr=NULL,*fmm=NULL,*fdcl=NULL,*fdcr=NULL,*fdclh=NULL,*fdcrh=NULL, *frl=NULL, *frr=NULL; int ch_offset,symbol_offset; //uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1]; @@ -692,84 +692,84 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, int8_t delta = get_delta(p, config_type); nr_pdsch_dmrs_rx(ue,Ns,ue->nr_gold_pdsch[eNB_offset][Ns][symbol][0], &pilot[0],1000,0,nb_rb_pdsch+rb_offset); - if (config_type == pdsch_dmrs_type1){ + if (config_type == pdsch_dmrs_type1 && ue->fd_lin_interpolation == 1){ nushift = (p>>1)&1; ue->frame_parms.nushift = nushift; switch (delta) { - case 0://port 0,1 - fl = filt8_l0;//left interpolation Filter for DMRS config. 1 - fm = filt8_m0;//left middle interpolation Filter - fr = filt8_r0;//right interpolation Filter - fmm = filt8_mm0;;//middle middle interpolation Filter - fml = filt8_m0;//left middle interpolation Filter - fmr = filt8_mr0;//middle right interpolation Filter - fdcl = filt8_dcl0;//left DC interpolation Filter (even RB) - fdcr = filt8_dcr0;//right DC interpolation Filter (even RB) - fdclh = filt8_dcl0_h;//left DC interpolation Filter (odd RB) - fdcrh = filt8_dcr0_h;//right DC interpolation Filter (odd RB) - frl = NULL; - frr = NULL; - break; + case 0://port 0,1 + fl = filt8_l0;//left interpolation Filter for DMRS config. 1 + fm = filt8_m0;//left middle interpolation Filter + fr = filt8_r0;//right interpolation Filter + fmm = filt8_mm0;;//middle middle interpolation Filter + fml = filt8_m0;//left middle interpolation Filter + fmr = filt8_mr0;//middle right interpolation Filter + fdcl = filt8_dcl0;//left DC interpolation Filter (even RB) + fdcr = filt8_dcr0;//right DC interpolation Filter (even RB) + fdclh = filt8_dcl0_h;//left DC interpolation Filter (odd RB) + fdcrh = filt8_dcr0_h;//right DC interpolation Filter (odd RB) + frl = NULL; + frr = NULL; + break; - case 1://port2,3 - fl = filt8_l1; - fm = filt8_m1; - fr = filt8_r1; - fmm = filt8_mm1; - fml = filt8_ml1; - fmr = filt8_m1; - fdcl = filt8_dcl1; - fdcr = filt8_dcr1; - fdclh = filt8_dcl1_h; - fdcrh = filt8_dcr1_h; - frl = NULL; - frr = NULL; - break; + case 1://port2,3 + fl = filt8_l1; + fm = filt8_m1; + fr = filt8_r1; + fmm = filt8_mm1; + fml = filt8_ml1; + fmr = filt8_m1; + fdcl = filt8_dcl1; + fdcr = filt8_dcr1; + fdclh = filt8_dcl1_h; + fdcrh = filt8_dcr1_h; + frl = NULL; + frr = NULL; + break; - default: - msg("pdsch_channel_estimation: nushift=%d -> ERROR\n",nushift); - return -1; - break; + default: + LOG_E(PHY,"pdsch_channel_estimation: nushift=%d -> ERROR\n",nushift); + return -1; + break; } - } else {//pdsch_dmrs_type2 + } else if (ue->fd_lin_interpolation == 1) {//pdsch_dmrs_type2 nushift = delta; ue->frame_parms.nushift = nushift; switch (delta) { - case 0://port 0,1 - fl = filt8_l2;//left interpolation Filter should be fml - fr = filt8_r2;//right interpolation Filter should be fmr - fm = filt8_l2; - fmm = filt8_r2; - fml = filt8_ml2; - fmr = filt8_mr2; - frl = filt8_rl2; - frr = filt8_rm2; - fdcl = filt8_dcl1; - fdcr = filt8_dcr1; - fdclh = filt8_dcl1_h; - fdcrh = filt8_dcr1_h; - break; + case 0://port 0,1 + fl = filt8_l2;//left interpolation Filter should be fml + fr = filt8_r2;//right interpolation Filter should be fmr + fm = filt8_l2; + fmm = filt8_r2; + fml = filt8_ml2; + fmr = filt8_mr2; + frl = filt8_rl2; + frr = filt8_rm2; + fdcl = filt8_dcl1; + fdcr = filt8_dcr1; + fdclh = filt8_dcl1_h; + fdcrh = filt8_dcr1_h; + break; - case 2://port2,3 - fl = filt8_l3; - fm = filt8_m2; - fr = filt8_r3; - fmm = filt8_mm2; - fml = filt8_l2; - fmr = filt8_r2; - frl = filt8_rl3; - frr = filt8_rr3; - fdcl = NULL; - fdcr = NULL; - fdclh = NULL; - fdcrh = NULL; - break; + case 2://port2,3 + fl = filt8_l3; + fm = filt8_m2; + fr = filt8_r3; + fmm = filt8_mm2; + fml = filt8_l2; + fmr = filt8_r2; + frl = filt8_rl3; + frr = filt8_rr3; + fdcl = NULL; + fdcr = NULL; + fdclh = NULL; + fdcrh = NULL; + break; - default: - msg("pdsch_channel_estimation: nushift=%d -> ERROR\n",nushift); - return -1; - break; + default: + LOG_E(PHY,"pdsch_channel_estimation: nushift=%d -> ERROR\n",nushift); + return -1; + break; } } @@ -791,8 +791,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, printf("rxF addr %p p %d\n", rxF,p); printf("dl_ch addr %p nushift %d\n",dl_ch,nushift); #endif - - if (config_type == pdsch_dmrs_type1) { + + if (config_type == pdsch_dmrs_type1 && ue->fd_lin_interpolation == 1) { // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -846,8 +846,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pdsch-3); pilot_cnt+=2) { //if ((pilot_cnt%6)==0) - //dl_ch+=4; - //printf("re_offset %d\n",re_offset); + //dl_ch+=4; + //printf("re_offset %d\n",re_offset); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -883,7 +883,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PDSCH - printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); + printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif multadd_real_vector_complex_scalar(fm, ch, @@ -923,59 +923,59 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - // check if PRB crosses DC and improve estimates around DC - if ((bwp_start_subcarrier < ue->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pdsch*12 >= ue->frame_parms.ofdm_symbol_size)) { - dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; - uint16_t idxDC = 2*(ue->frame_parms.ofdm_symbol_size - bwp_start_subcarrier); - uint16_t idxPil = idxDC/2; - re_offset = k; - pil = (int16_t *)&pilot[rb_offset*((config_type==pdsch_dmrs_type1) ? 6:4)]; - pil += (idxPil-2); - dl_ch += (idxDC-4); - dl_ch = memset(dl_ch, 0, sizeof(int16_t)*10); - re_offset = (re_offset+idxDC/2-2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + // check if PRB crosses DC and improve estimates around DC + if ((bwp_start_subcarrier < ue->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pdsch*12 >= ue->frame_parms.ofdm_symbol_size)) { + dl_ch = (int16_t *)&dl_ch_estimates[aarx][ch_offset]; + uint16_t idxDC = 2*(ue->frame_parms.ofdm_symbol_size - bwp_start_subcarrier); + uint16_t idxPil = idxDC/2; + re_offset = k; + pil = (int16_t *)&pilot[rb_offset*((config_type==pdsch_dmrs_type1) ? 6:4)]; + pil += (idxPil-2); + dl_ch += (idxDC-4); + dl_ch = memset(dl_ch, 0, sizeof(int16_t)*10); + re_offset = (re_offset+idxDC/2-2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - // for proper allignment of SIMD vectors - if((ue->frame_parms.N_RB_DL&1)==0) { + // for proper allignment of SIMD vectors + if((ue->frame_parms.N_RB_DL&1)==0) { - multadd_real_vector_complex_scalar(fdcl, - ch, - dl_ch-4, - 8); + multadd_real_vector_complex_scalar(fdcl, + ch, + dl_ch-4, + 8); - pil += 4; - re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + pil += 4; + re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - multadd_real_vector_complex_scalar(fdcr, - ch, - dl_ch-4, - 8); - } else { + multadd_real_vector_complex_scalar(fdcr, + ch, + dl_ch-4, + 8); + } else { - multadd_real_vector_complex_scalar(fdclh, - ch, - dl_ch, - 8); + multadd_real_vector_complex_scalar(fdclh, + ch, + dl_ch, + 8); - pil += 4; - re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + pil += 4; + re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - multadd_real_vector_complex_scalar(fdcrh, - ch, - dl_ch, - 8); + multadd_real_vector_complex_scalar(fdcrh, + ch, + dl_ch, + 8); + } } - } - } else { //pdsch_dmrs_type2 |dmrs_r,dmrs_l,0,0,0,0,dmrs_r,dmrs_l,0,0,0,0| + } else if (config_type==pdsch_dmrs_type2 && ue->fd_lin_interpolation == 1){ //pdsch_dmrs_type2 |dmrs_r,dmrs_l,0,0,0,0,dmrs_r,dmrs_l,0,0,0,0| // Treat first 4 pilots specially (left edge) ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -1187,7 +1187,96 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, } } } + else if (config_type==pdsch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + + for (pilot_cnt=0; pilot_cnt<6*nb_rb_pdsch; pilot_cnt+=6) { + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0]/=6; + ch[1]/=6; + ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); + ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; + ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; + dl_ch+=24; + } + } + else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + for (pilot_cnt=0; pilot_cnt<4*nb_rb_pdsch; pilot_cnt+=4) { + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0]>>=2; + ch[1]>>=2; + ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); + ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; + ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; + dl_ch+=24; + } + } #ifdef DEBUG_PDSCH dl_ch = (int16_t *)&dl_ch_estimates[p*ue->frame_parms.nb_antennas_rx+aarx][ch_offset]; for(uint16_t idxP=0; idxPnb_antennas_rx;aarx++) avgs = cmax(avgs,avg[(aatx<<1)+aarx]); - pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2)+3; + pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2)+1; } else if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 390574a66b..bcc24610ff 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -852,6 +852,9 @@ typedef struct { uint32_t high_speed_flag; uint32_t perfect_ce; + // flag to activate linear interpolation in frequency-domain channel estimation + // when off (default), this just averages channel on per-PRB basis + uint32_t fd_lin_interpolation; int16_t ch_est_alpha; int generate_ul_signal[NUMBER_OF_CONNECTED_gNB_MAX]; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 9581038283..6860dd5c6b 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1168,7 +1168,7 @@ int main(int argc, char **argv) LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1); if (UE->frame_parms.nb_antennas_rx>1) LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1); - LOG_M("chestF0.m","chF0",UE->pdsch_vars[0][0]->dl_ch_estimates_ext,N_RB_DL*12*14,1,1); + LOG_M("chestF0.m","chF0",&UE->pdsch_vars[0][0]->dl_ch_estimates_ext[0][0],g_rbSize*12*14,1,1); write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1); LOG_M("rxF_llr.m","rxFllr",UE->pdsch_vars[UE_proc.thread_id][0]->llr[0],available_bits,1,0); break; From e881a108cd09a3516a21f5786ee5af6f0d23bea5 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 26 Feb 2021 11:03:15 +0100 Subject: [PATCH 003/185] Added encoding stats in ulsim --- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 3 ++- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 23 ++++++++++--------- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 2 +- openair1/SIMULATION/NR_PHY/ulschsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 10 ++++++++ 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 91274b908a..d6489f02f6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1041,7 +1041,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint8_t is_crnti, uint8_t llr8_flag); -int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, +int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, + NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS* frame_parms, uint8_t harq_pid, unsigned int G); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index d9bea8a3ac..99572cc9cd 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -215,11 +215,13 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL, } -int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, +int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, + NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS* frame_parms, uint8_t harq_pid, unsigned int G) { + start_meas(&ue->ulsch_encoding_stats); /////////////////////////parameters and variables declaration///////////////////////// /////////// @@ -331,6 +333,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_IN); + start_meas(&ue->ulsch_segmentation_stats); Kb=nr_segmentation(harq_process->b, harq_process->c, harq_process->B, @@ -339,6 +342,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, pz, &harq_process->F, harq_process->BG); + stop_meas(&ue->ulsch_segmentation_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_SEGMENTATION, VCD_FUNCTION_OUT); F = harq_process->F; @@ -373,14 +377,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, //for (int i=0;i<68*384;i++) // printf("channel_input[%d]=%d\n",i,channel_input[i]); - int temp_opp = 0; - - if (opp_enabled) { - opp_enabled = 0; - temp_opp = 1; - } - - /*printf("output %d %d %d %d %d \n", harq_process->d[0][0], harq_process->d[0][1], harq_process->d[r][2],harq_process->d[0][3], harq_process->d[0][4]); for (int cnt =0 ; cnt < 66*(*pz); cnt ++){ printf("%d \n", harq_process->d[0][cnt]); @@ -396,11 +392,13 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN); + start_meas(&ue->ulsch_ldpc_encoding_stats); for(int j = 0; j < (harq_process->C/8 + 1); j++) { impp.macro_num = j; nrLDPC_encoder(harq_process->c,harq_process->d,*pz,Kb,Kr,harq_process->BG,&impp); } + stop_meas(&ue->ulsch_ldpc_encoding_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_OUT); @@ -411,8 +409,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, write_output("ulsch_enc_output0.m","enc0",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,4); #endif - if (temp_opp) opp_enabled = 1; - /////////// /////////////////////////////////////////////////////////////////////////////// @@ -447,6 +443,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, Tbslbrm = nr_compute_tbslbrm(0,nb_rb,harq_process->pusch_pdu.nrOfLayers); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN); + start_meas(&ue->ulsch_rate_matching_stats); nr_rate_matching_ldpc(Ilbrm, Tbslbrm, harq_process->BG, @@ -458,6 +455,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, Kr-F-2*(*pz), harq_process->pusch_pdu.pusch_data.rv_index, E); + stop_meas(&ue->ulsch_rate_matching_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_OUT); @@ -479,10 +477,12 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, //start_meas(i_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_IN); + start_meas(&ue->ulsch_interleaving_stats); nr_interleaving_ldpc(E, mod_order, harq_process->e+r_offset, harq_process->f+r_offset); + stop_meas(&ue->ulsch_interleaving_stats); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INTERLEAVING_LDPC, VCD_FUNCTION_OUT); //stop_meas(i_stats); @@ -507,5 +507,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_UE_ULSCH_ENCODING, VCD_FUNCTION_OUT); + stop_meas(&ue->ulsch_encoding_stats); return(0); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 208901f289..8af487b35b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -157,7 +157,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, nb_dmrs_re_per_rb, number_dmrs_symbols, mod_order, Nl); - nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid, G); + nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, G); /////////// //////////////////////////////////////////////////////////////////// diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 6f2af73a1d..7deb0b66d1 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -504,7 +504,7 @@ int main(int argc, char **argv) unsigned int G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, Nl); if (input_fd == NULL) { - nr_ulsch_encoding(ulsch_ue, frame_parms, harq_pid, G); + nr_ulsch_encoding(ue, ulsch_ue, frame_parms, harq_pid, G); } printf("\n"); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 443ee6e1c0..8c1396f224 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -906,6 +906,10 @@ int main(int argc, char **argv) reset_meas(&gNB->ulsch_llr_stats); reset_meas(&gNB->ulsch_channel_compensation_stats); reset_meas(&gNB->ulsch_rbs_extraction_stats); + reset_meas(&UE->ulsch_ldpc_encoding_stats); + reset_meas(&UE->ulsch_rate_matching_stats); + reset_meas(&UE->ulsch_interleaving_stats); + reset_meas(&UE->ulsch_encoding_stats); clear_pusch_stats(gNB); for (trial = 0; trial < n_trials; trial++) { @@ -914,6 +918,7 @@ int main(int argc, char **argv) crc_status = 1; errors_decoding = 0; memset((void*)roundStats,0,50*sizeof(roundStats[0])); + ulsch_ue[0]->harq_processes[harq_pid]->ndi = 1; while (roundharq_processes[harq_pid]->round = round; @@ -1278,6 +1283,11 @@ int main(int argc, char **argv) printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation"); printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling"); printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time"); + printStatIndent(&UE->ulsch_encoding_stats,"ULSCH total encoding time"); + printStatIndent2(&UE->ulsch_segmentation_stats,"ULSCH segmentation time"); + printStatIndent2(&UE->ulsch_ldpc_encoding_stats,"ULSCH LDPC encoder time"); + printStatIndent2(&UE->ulsch_rate_matching_stats,"ULSCH rate-matching time"); + printStatIndent2(&UE->ulsch_interleaving_stats,"ULSCH interleaving time"); //printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving"); //printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx"); //printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding"); From 9fce798a0ee768caa3c4a62470a97e8d44ad169c Mon Sep 17 00:00:00 2001 From: Shruthi Date: Wed, 3 Mar 2021 23:09:02 +0530 Subject: [PATCH 004/185] Fixed errors in nFAPI after first merge --- executables/nr-gnb.c | 40 +- executables/nr-ru.c | 32 +- executables/nr-ru_Original.c | 2514 +++++++++++++++++ nfapi/oai_integration/nfapi_pnf.c | 2 + nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 16 +- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 5 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 1 + openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c | 22 +- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 4 +- openair1/SCHED_NR/fapi_nr_l1.c | 31 +- openair1/SCHED_NR/phy_frame_config_nr.c | 2 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 1 + openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 1 + openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 26 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 16 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 1 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 11 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 3 + openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 10 +- 19 files changed, 2682 insertions(+), 56 deletions(-) create mode 100644 executables/nr-ru_Original.c diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index cd1bfd14b6..8ed4ac2e1c 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -252,8 +252,25 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t pthread_mutex_unlock(&gNB->UL_INFO_mutex); // RX processing - int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); - int rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); + int tx_slot_type; int rx_slot_type; + if(NFAPI_MODE == NFAPI_MODE_VNF) { + if ((slot_tx==8) || (slot_rx==8) || (slot_tx==9) || (slot_rx==9) || (slot_tx==18) || (slot_rx==18) || (slot_tx==19) || (slot_rx==19)) { + tx_slot_type = NR_UPLINK_SLOT; + rx_slot_type = NR_UPLINK_SLOT; + } + else if ((slot_tx==7) || (slot_rx==7) || (slot_tx==17) || (slot_rx==17)) { + tx_slot_type = NR_MIXED_SLOT; + rx_slot_type = NR_MIXED_SLOT; + } + else { + tx_slot_type = NR_DOWNLINK_SLOT; + rx_slot_type = NR_DOWNLINK_SLOT; + } + } + else { + tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); + rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); + } if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { // UE-specific RX processing for subframe n @@ -400,15 +417,21 @@ static void *gNB_L1_thread( void *param ) { while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); - if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); int frame_rx = L1_proc->frame_rx; int slot_rx = L1_proc->slot_rx; int frame_tx = L1_proc->frame_tx; int slot_tx = L1_proc->slot_tx; uint64_t timestamp_tx = L1_proc->timestamp_tx; + if(NFAPI_MODE==NFAPI_MODE_VNF) + if (gNB->CC_id==0) { + int next_slot; + next_slot = (slot_rx + 1) % 20; + if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break + } + if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx); @@ -422,9 +445,12 @@ static void *gNB_L1_thread( void *param ) { if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break; } + clock_gettime(CLOCK_MONOTONIC,&t); + //printf("\n %d.%d",t.tv_sec,t.tv_nsec); + if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break; - - if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx); + + if (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx); else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx); } // while !oai_exit diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 73421d8ed7..1184a9d80c 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -97,7 +97,8 @@ static int DEFBFW[] = {0x00007fff}; extern volatile int oai_exit; - +extern struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); +extern struct timespec timespec_add(struct timespec lhs, struct timespec rhs); extern void nr_phy_free_RU(RU_t *); extern void nr_phy_config_request(NR_PHY_Config_t *gNB); #include "executables/thread-common.h" @@ -710,6 +711,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { + RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -1541,9 +1543,35 @@ void *ru_thread( void *param ) { pthread_cond_signal(&proc->cond_FH1); // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + struct timespec slot_start; + clock_gettime(CLOCK_MONOTONIC, &slot_start); + + struct timespec slot_duration; + slot_duration.tv_sec = 0; + //slot_duration.tv_nsec = 0.5e6; + slot_duration.tv_nsec = 0.5e6; + + + while (!oai_exit) { // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. // They are set on the first rx/tx in the underly FH routines. + slot_start = timespec_add(slot_start,slot_duration); + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + + struct timespec sleep_time; + + if((slot_start.tv_sec > curr_time.tv_sec) || (slot_start.tv_sec == curr_time.tv_sec && slot_start.tv_nsec > curr_time.tv_nsec)){ + sleep_time = timespec_sub(slot_start,curr_time); + + usleep(sleep_time.tv_nsec * 1e-3); + } + else{//continue + } + + // clock_gettime(CLOCK_MONOTONIC, &curr_time); + //printf("sfn:%d, slot:%d, start time %d.%d slot start %d.%d \n",frame,slot,curr_time.tv_sec,curr_time.tv_nsec,slot_start.tv_sec,slot_start.tv_nsec); if (slot==(fp->slots_per_frame-1)) { slot=0; frame++; @@ -1562,7 +1590,7 @@ void *ru_thread( void *param ) { proc->frame_rx,proc->tti_rx, proc->frame_tx,proc->tti_tx, RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); + RC.gNB[0]->proc.frame_tx); /* LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", ru->do_prach, diff --git a/executables/nr-ru_Original.c b/executables/nr-ru_Original.c new file mode 100644 index 0000000000..73421d8ed7 --- /dev/null +++ b/executables/nr-ru_Original.c @@ -0,0 +1,2514 @@ +/* + * 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 + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "common/utils/assertions.h" +#include "common/utils/system.h" +#include "msc.h" + +#include "../../ARCH/COMMON/common_lib.h" +#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" + +#include "PHY/LTE_TRANSPORT/if4_tools.h" +#include "PHY/LTE_TRANSPORT/if5_tools.h" + +#include "PHY/types.h" +#include "PHY/defs_nr_common.h" +#include "PHY/phy_extern.h" +#include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" +#include "PHY/INIT/phy_init.h" +#include "SCHED/sched_eNB.h" +#include "SCHED_NR/sched_nr.h" + +#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" +#include "RRC/LTE/rrc_extern.h" +#include "PHY_INTERFACE/phy_interface.h" + +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#include "enb_config.h" +#include + +#ifdef SMBV +#include "PHY/TOOLS/smbv.h" +unsigned short config_frames[4] = {2,9,11,13}; +#endif + +/* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */ +static int DEFBANDS[] = {7}; +static int DEFENBS[] = {0}; +static int DEFBFW[] = {0x00007fff}; + +//static int DEFNRBANDS[] = {7}; +//static int DEFGNBS[] = {0}; + +#include "ENB_APP/enb_paramdef.h" +#include "GNB_APP/gnb_paramdef.h" +#include "common/config/config_userapi.h" + +#ifndef OPENAIR2 + #include "UTIL/OTG/otg_extern.h" +#endif + +#include "s1ap_eNB.h" +#include "SIMULATION/ETH_TRANSPORT/proto.h" + + + +#include "T.h" +#include "nfapi_interface.h" + +extern volatile int oai_exit; + + +extern void nr_phy_free_RU(RU_t *); +extern void nr_phy_config_request(NR_PHY_Config_t *gNB); +#include "executables/thread-common.h" +//extern PARALLEL_CONF_t get_thread_parallel_conf(void); +//extern WORKER_CONF_t get_thread_worker_conf(void); + +void init_NR_RU(char *); +void stop_RU(int nb_ru); +void do_ru_sync(RU_t *ru); + +void configure_ru(int idx, void *arg); +void configure_rru(int idx, void *arg); +int attach_rru(RU_t *ru); +int connect_rau(RU_t *ru); + +uint16_t sf_ahead; +uint16_t slot_ahead; +uint16_t sl_ahead; + +extern int emulate_rf; +extern int numerology; +extern int usrp_tx_thread; + +/*************************************************************/ +/* Functions to attach and configure RRU */ + +extern void wait_gNBs(void); + +int attach_rru(RU_t *ru) +{ + ssize_t msg_len,len; + RRU_CONFIG_msg_t rru_config_msg; + int received_capabilities=0; + wait_gNBs(); + + // Wait for capabilities + while (received_capabilities==0) { + memset((void *)&rru_config_msg,0,sizeof(rru_config_msg)); + rru_config_msg.type = RAU_tick; + rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE; + LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx); + AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), + "RU %d cannot access remote radio\n",ru->idx); + msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); + + // wait for answer with timeout + if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, + &rru_config_msg, + msg_len))<0) { + LOG_I(PHY,"Waiting for RRU %d\n",ru->idx); + } else if (rru_config_msg.type == RRU_capabilities) { + AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len); + LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx, + (int)rru_config_msg.len,(int)msg_len, + ((RRU_capabilities_t *)&rru_config_msg.msg[0])->num_bands, + ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0], + ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_rxgain[0], + ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_tx[0], + ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_rx[0]); + received_capabilities=1; + } else { + LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); + } + } + + configure_ru(ru->idx, + (RRU_capabilities_t *)&rru_config_msg.msg[0]); + rru_config_msg.type = RRU_config; + rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); + LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx, + ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands, + ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); + AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), + "RU %d failed send configuration to remote radio\n",ru->idx); + + if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, + &rru_config_msg, + msg_len))<0) { + LOG_I(PHY,"Waiting for RRU %d\n",ru->idx); + } else if (rru_config_msg.type == RRU_config_ok) { + LOG_I(PHY, "RRU_config_ok received\n"); + } else { + LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); + } + + return 0; +} + +int connect_rau(RU_t *ru) +{ + RRU_CONFIG_msg_t rru_config_msg; + ssize_t msg_len; + int tick_received = 0; + int configuration_received = 0; + RRU_capabilities_t *cap; + int i; + int len; + + // wait for RAU_tick + while (tick_received == 0) { + msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE; + + if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, + &rru_config_msg, + msg_len))<0) { + LOG_I(PHY,"Waiting for RAU\n"); + } else { + if (rru_config_msg.type == RAU_tick) { + LOG_I(PHY,"Tick received from RAU\n"); + tick_received = 1; + } else LOG_E(PHY,"Received erroneous message (%d)from RAU, expected RAU_tick\n",rru_config_msg.type); + } + } + + // send capabilities + rru_config_msg.type = RRU_capabilities; + rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); + cap = (RRU_capabilities_t *)&rru_config_msg.msg[0]; + LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n", + (int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx); + + switch (ru->function) { + case NGFI_RRU_IF4p5: + cap->FH_fmt = OAI_IF4p5_only; + break; + + case NGFI_RRU_IF5: + cap->FH_fmt = OAI_IF5_only; + break; + + case MBP_RRU_IF5: + cap->FH_fmt = MBP_IF5; + break; + + default: + AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function); + break; + } + + cap->num_bands = ru->num_bands; + + for (i=0; inum_bands; i++) { + LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n", + ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain); + cap->band_list[i] = ru->band[i]; + cap->nb_rx[i] = ru->nb_rx; + cap->nb_tx[i] = ru->nb_tx; + cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower; + cap->max_rxgain[i] = ru->max_rxgain; + } + + AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), + "RU %d failed send capabilities to RAU\n",ru->idx); + // wait for configuration + rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); + + while (configuration_received == 0) { + if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, + &rru_config_msg, + rru_config_msg.len))<0) { + LOG_I(PHY,"Waiting for configuration from RAU\n"); + } else { + LOG_I(PHY,"Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n", + ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands, + ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0], + ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); + configure_rru(ru->idx, + (void *)&rru_config_msg.msg[0]); + configuration_received = 1; + } + } + + return 0; +} +/*************************************************************/ +/* Southbound Fronthaul functions, RCC/RAU */ + +// southbound IF5 fronthaul for 16-bit OAI format +void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) +{ + if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + + send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL); +} + +// southbound IF4p5 fronthaul +void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) +{ + nfapi_nr_config_request_scf_t *cfg = &ru->config; + if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + + LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx); + + + if ((nr_slot_select(cfg,ru->proc.frame_tx,ru->proc.tti_tx)&NR_DOWNLINK_SLOT) > 0) + send_IF4p5(ru,frame, slot, IF4p5_PDLFFT); +} + +/*************************************************************/ +/* Input Fronthaul from south RCC/RAU */ + +// Synchronous if5 from south +void fh_if5_south_in(RU_t *ru, + int *frame, + int *tti) +{ + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + RU_proc_t *proc = &ru->proc; + recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL); + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; + uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe; + proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); + + if (proc->first_rx == 0) { + if (proc->tti_rx != *tti) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*tti); + exit_fun("Exiting"); + } + + if (proc->frame_rx != *frame) { + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *tti = proc->tti_rx; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); +} + +// Synchronous if4p5 from south +void fh_if4p5_south_in(RU_t *ru, + int *frame, + int *slot) +{ + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + RU_proc_t *proc = &ru->proc; + int f,sl; + uint16_t packet_type; + uint32_t symbol_number=0; + uint32_t symbol_mask_full=0; + + /* + if ((fp->frame_type == TDD) && (subframe_select(fp,*slot)==SF_S)) + symbol_mask_full = (1<ul_symbols_in_S_subframe)-1; + else + symbol_mask_full = (1<symbols_per_slot)-1; + + AssertFatal(proc->symbol_mask[*slot]==0,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*slot,proc->symbol_mask[*slot]);*/ + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! + recv_IF4p5(ru, &f, &sl, &packet_type, &symbol_number); + + if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sl] = proc->symbol_mask[sl] | (1<first_rx==0) && (f!=*frame)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d\n",f,*frame); + + if ((proc->first_rx==0) && (sl!=*slot)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n",sl,*slot,proc->first_rx); + + break; + } else if (packet_type == IF4p5_PRACH) { + // nothing in RU for RAU + } + + LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*slot,proc->symbol_mask[sl]); + } while(proc->symbol_mask[sl] != symbol_mask_full); + + //caculate timestamp_rx, timestamp_tx based on frame and subframe + proc->tti_rx = sl; + proc->frame_rx = f; + proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(proc->tti_rx, fp, 0); + // proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_subframe); + proc->tti_tx = (sl+(fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; + proc->frame_tx = (sl>(fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (f+1)&1023 : f; + + if (proc->first_rx == 0) { + if (proc->tti_rx != *slot) { + LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*slot); + exit_fun("Exiting"); + } + + if (proc->frame_rx != *frame) { + LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *slot = proc->tti_rx; + } + + if (ru == RC.ru[0]) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, sl); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx ); + } + + proc->symbol_mask[proc->tti_rx] = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + LOG_D(PHY,"RU %d: fh_if4p5_south_in sleeping ...\n",ru->idx); +} + +// asynchronous inbound if4p5 fronthaul from south +void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *slot) { + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + RU_proc_t *proc = &ru->proc; + uint16_t packet_type; + uint32_t symbol_number,symbol_mask,prach_rx; + // uint32_t got_prach_info=0; + symbol_number = 0; + symbol_mask = (1<<(fp->symbols_per_slot))-1; + prach_rx = 0; + + do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! + recv_IF4p5(ru, &proc->frame_rx, &proc->tti_rx, &packet_type, &symbol_number); + + // grab first prach information for this new subframe + /*if (got_prach_info==0) { + prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->tti_rx); + got_prach_info = 1; + }*/ + if (proc->first_rx != 0) { + *frame = proc->frame_rx; + *slot = proc->tti_rx; + proc->first_rx = 0; + } else { + if (proc->frame_rx != *frame) { + LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame); + exit_fun("Exiting"); + } + + if (proc->tti_rx != *slot) { + LOG_E(PHY,"tti_rx %d is not what we expect %d\n",proc->tti_rx,*slot); + exit_fun("Exiting"); + } + } + + if (packet_type == IF4p5_PULFFT) symbol_mask &= (~(1< 0) || (prach_rx >0)); // haven't received all PUSCH symbols and PRACH information +} + + + + + +/*************************************************************/ +/* Input Fronthaul from North RRU */ + +// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output +// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates +void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot) { + uint32_t symbol_number=0; + uint32_t symbol_mask, symbol_mask_full; + uint16_t packet_type; + /// **** incoming IF4p5 from remote RCC/RAU **** /// + symbol_number = 0; + symbol_mask = 0; + symbol_mask_full = (1<<(ru->nr_frame_parms->symbols_per_slot))-1; + + do { + recv_IF4p5(ru, frame, slot, &packet_type, &symbol_number); + symbol_mask = symbol_mask | (1<nr_frame_parms; + RU_proc_t *proc = &ru->proc; + int tti_tx,frame_tx; + openair0_timestamp timestamp_tx; + recv_IF5(ru, ×tamp_tx, *slot, IF5_RRH_GW_DL); + // printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); + frame_tx = (timestamp_tx / (fp->samples_per_subframe*10))&1023; + uint32_t idx_sf = timestamp_tx / fp->samples_per_subframe; + tti_tx = (idx_sf * fp->slots_per_subframe + (int)round((float)(timestamp_tx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); + + if (proc->first_tx != 0) { + *slot = tti_tx; + *frame = frame_tx; + proc->first_tx = 0; + } else { + AssertFatal(tti_tx == *slot, + "tti_tx %d is not what we expect %d\n",tti_tx,*slot); + AssertFatal(frame_tx == *frame, + "frame_tx %d is not what we expect %d\n",frame_tx,*frame); + } +} + +void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) { + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + nfapi_nr_config_request_scf_t *cfg = &ru->config; + RU_proc_t *proc = &ru->proc; + uint16_t packet_type; + uint32_t symbol_number,symbol_mask,symbol_mask_full=0; + int slot_tx,frame_tx; + LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru); + symbol_number = 0; + symbol_mask = 0; + + // symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<dl_symbols_in_S_subframe) : (1<symbols_per_slot))-1; + do { + recv_IF4p5(ru, &frame_tx, &slot_tx, &packet_type, &symbol_number); + + if (((nr_slot_select(cfg,frame_tx,slot_tx) & NR_DOWNLINK_SLOT) > 0) && (symbol_number == 0)) start_meas(&ru->rx_fhaul); + + LOG_D(PHY,"slot %d (%d): frame %d, slot %d, symbol %d\n", + *slot,nr_slot_select(cfg,frame_tx,*slot),frame_tx,slot_tx,symbol_number); + + if (proc->first_tx != 0) { + *frame = frame_tx; + *slot = slot_tx; + proc->first_tx = 0; + //symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<dl_symbols_in_S_subframe) : (1<symbols_per_slot))-1; + } else { + AssertFatal(frame_tx == *frame, + "frame_tx %d is not what we expect %d\n",frame_tx,*frame); + AssertFatal(slot_tx == *slot, + "slot_tx %d is not what we expect %d\n",slot_tx,*slot); + } + + if (packet_type == IF4p5_PDLFFT) { + symbol_mask = symbol_mask | (1<0) stop_meas(&ru->rx_fhaul); + + proc->tti_tx = slot_tx; + proc->frame_tx = frame_tx; + + if ((frame_tx == 0)&&(slot_tx == 0)) proc->frame_tx_unwrap += 1024; + + proc->timestamp_tx = (((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(slot_tx, fp, 0); + LOG_D(PHY,"RU %d/%d TST %llu, frame %d, subframe %d\n",ru->idx,0,(long long unsigned int)proc->timestamp_tx,frame_tx,slot_tx); + + // dump VCD output for first RU in list + if (ru == RC.ru[0]) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot_tx ); + } + + if (ru->feptx_ofdm) ru->feptx_ofdm(ru,frame_tx,slot_tx); + + if (ru->fh_south_out) ru->fh_south_out(ru,frame_tx,slot_tx,proc->timestamp_tx); +} + +void fh_if5_north_out(RU_t *ru) { + RU_proc_t *proc=&ru->proc; + uint8_t seqno=0; + /// **** send_IF5 of rxdata to BBU **** /// + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); + send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); +} + +// RRU IF4p5 northbound interface (RX) +void fh_if4p5_north_out(RU_t *ru) { + RU_proc_t *proc=&ru->proc; + + //NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + //const int subframe = proc->tti_rx; + if (ru->idx==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); + + /* + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) { + /// **** in TDD during DL send_IF4 of ULTICK to RCC **** /// + send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULTICK); + return; + }*/ + start_meas(&ru->tx_fhaul); + send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULFFT); + stop_meas(&ru->tx_fhaul); +} + +void *emulatedRF_thread(void *param) { + RU_proc_t *proc = (RU_proc_t *) param; + int microsec = 500; // length of time to sleep, in miliseconds + struct timespec req = {0}; + req.tv_sec = 0; + req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2; + wait_sync("emulatedRF_thread"); + + while(!oai_exit) { + nanosleep(&req, (struct timespec *)NULL); + pthread_mutex_lock(&proc->mutex_emulateRF); + ++proc->instance_cnt_emulateRF; + pthread_mutex_unlock(&proc->mutex_emulateRF); + pthread_cond_signal(&proc->cond_emulateRF); + } + + return 0; +} + +void rx_rf(RU_t *ru,int *frame,int *slot) { + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + void *rxp[ru->nb_rx]; + unsigned int rxs; + int i; + uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp); + uint32_t samples_per_slot_prev ; + openair0_timestamp ts,old_ts; + AssertFatal(*slotslots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame); + + for (i=0; inb_rx; i++) + rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)]; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); + old_ts = proc->timestamp_rx; + LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]); + + if(emulate_rf) { + wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); + release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); + rxs = samples_per_slot; + ts = old_ts + rxs; + } else { + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &ts, + rxp, + samples_per_slot, + ru->nb_rx); + } + + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); + proc->timestamp_rx = ts-ru->ts_offset; + + //AssertFatal(rxs == fp->samples_per_subframe, + //"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs); + if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",samples_per_slot,rxs); + + if (proc->first_rx == 1) { + ru->ts_offset = proc->timestamp_rx; + proc->timestamp_rx = 0; + } else { + samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp); + if (proc->timestamp_rx - old_ts != samples_per_slot_prev) { + LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot_prev,ru->ts_offset); + ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot_prev); + proc->timestamp_rx = ts-ru->ts_offset; + } + } + + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; + proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx,fp); + // synchronize first reception to frame 0 subframe 0 + LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n", + ru->idx, + 0, + (unsigned long long int)proc->timestamp_rx, + (int)ru->ts_offset,proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame); + + // dump VCD output for first RU in list + if (ru == RC.ru[0]) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); + } + + if (proc->first_rx == 0) { + if (proc->tti_rx != *slot) { + LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot); + exit_fun("Exiting"); + } + + if (proc->frame_rx != *frame) { + LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame,proc->tti_rx,*slot); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *slot = proc->tti_rx; + } + + //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + + if (rxs != samples_per_slot) { + //exit_fun( "problem receiving samples" ); + LOG_E(PHY, "problem receiving samples\n"); + } +} + + +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + nfapi_nr_config_request_scf_t *cfg = &ru->config; + void *txp[ru->nb_tx]; + unsigned int txs; + int i,txsymb; + T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot), + T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4)); + + int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); + int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame); + int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame); + int sf_extension = 0; //sf_extension = ru->sf_extension; + int siglen=fp->get_samples_per_slot(slot,fp); + int flags=1; + + //nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame); + if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) { + + if (cfg->cell_config.frame_duplex_type.value == TDD){ + if(slot_type == NR_MIXED_SLOT) { + txsymb = 0; + for(int symbol_count = 0; symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) + txsymb++; + } + AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb); + if(slot%(fp->slots_per_subframe/2)) + siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + else + siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + //+ ru->end_of_burst_delay; + flags = 3; // end of burst + } + + if (slot_type == NR_DOWNLINK_SLOT && prevslot_type == NR_UPLINK_SLOT) + flags = 2; // start of burst + + if (slot_type == NR_DOWNLINK_SLOT && nextslot_type == NR_UPLINK_SLOT) + flags = 3; // end of burst + } + + if (fp->freq_range==nr_FR2) { + // the beam index is written in bits 8-10 of the flags + // bit 11 enables the gpio programming + int beam=0; + //if (slot==0) beam = 11; //3 for boresight & 8 to enable + /* + if (slot==0 || slot==40) beam=0&8; + if (slot==10 || slot==50) beam=1&8; + if (slot==20 || slot==60) beam=2&8; + if (slot==30 || slot==70) beam=3&8; + */ + flags |= beam<<8; + } + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot ); + for (i=0; inb_tx; i++) + txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension]; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); + // prepare tx buffer pointers + txs = ru->rfdevice.trx_write_func(&ru->rfdevice, + timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %di, returned %d\n",ru->idx, + (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot, txs); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); + //AssertFatal(txs == 0,"trx write function error %d\n", txs); + } +} + + + +/*! + * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU. + * This handles the RX FH for an asynchronous RRU/UE + * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +void *ru_thread_asynch_rxtx( void *param ) { + static int ru_thread_asynch_rxtx_status; + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = &ru->proc; + nfapi_nr_config_request_scf_t *cfg = &ru->config; + int slot=0, frame=0; + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe + wait_sync("ru_thread_asynch_rxtx"); + // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe + printf( "waiting for devices (ru_thread_asynch_rx)\n"); + wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); + printf( "devices ok (ru_thread_asynch_rx)\n"); + + while (!oai_exit) { + + if (slot==ru->nr_frame_parms->slots_per_frame) { + slot=0; + frame++; + frame&=1023; + } else { + slot++; + } + + LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); + + // asynchronous receive from north (RRU IF4/IF5) + if (ru->fh_north_asynch_in) { + if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0) + ru->fh_north_asynch_in(ru,&frame,&slot); + } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n"); + } + + ru_thread_asynch_rxtx_status=0; + return(&ru_thread_asynch_rxtx_status); +} + + + + +/*! + * \brief The prach receive thread of RU. + * \param param is a \ref RU_proc_t structure which contains the info what to process. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ +void *ru_thread_prach( void *param ) { + static int ru_thread_prach_status; + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = (RU_proc_t *)&ru->proc; + // set default return value + ru_thread_prach_status = 0; + + while (RC.ru_mask>0) { + usleep(1e6); + LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__); + } + + LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__); + + while (!oai_exit) { + + + if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; + + /*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); + + if (ru->gNB_list[0]){ + prach_procedures( + ru->gNB_list[0],0 + ); + } + else { + rx_prach(NULL, + ru, + NULL, + NULL, + NULL, + proc->frame_prach, + 0,0 + ); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ + if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; + } + + LOG_I(PHY, "Exiting RU thread PRACH\n"); + ru_thread_prach_status = 0; + return &ru_thread_prach_status; +} + + +int wakeup_synch(RU_t *ru) { + struct timespec wait; + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + // wake up synch thread + // lock the synch mutex and make sure the thread is ready + if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) { + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch ); + exit_fun( "error locking mutex_synch" ); + return(-1); + } + + ++ru->proc.instance_cnt_synch; + + // the thread can now be woken up + if (pthread_cond_signal(&ru->proc.cond_synch) != 0) { + LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return(-1); + } + + pthread_mutex_unlock( &ru->proc.mutex_synch ); + return(0); +} + +void do_ru_synch(RU_t *ru) { + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + RU_proc_t *proc = &ru->proc; + int i; + void *rxp[2],*rxp2[2]; + int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32))); + int rxs; + int ic; + + // initialize the synchronization buffer to the common_vars.rxdata + for (int i=0; inb_rx; i++) + rxp[i] = &ru->common.rxdata[i][0]; + + double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0]; + double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0]; + + for (i=0; i<4; i++) { + ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i]; + ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1; + } + + ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); + + while ((ru->in_synch ==0)&&(!oai_exit)) { + // read in frame + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &(proc->timestamp_rx), + rxp, + fp->samples_per_subframe*10, + ru->nb_rx); + + if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs); + + // wakeup synchronization processing thread + wakeup_synch(ru); + ic=0; + + while ((ic>=0)&&(!oai_exit)) { + // continuously read in frames, 1ms at a time, + // until we are done with the synchronization procedure + for (i=0; inb_rx; i++) + rxp2[i] = (void *)&dummy_rx[i][0]; + + for (i=0; i<10; i++) + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &(proc->timestamp_rx), + rxp2, + fp->samples_per_subframe, + ru->nb_rx); + + pthread_mutex_lock(&ru->proc.mutex_synch); + ic = ru->proc.instance_cnt_synch; + pthread_mutex_unlock(&ru->proc.mutex_synch); + } // ic>=0 + } // in_synch==0 + + // read in rx_offset samples + LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset); + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &(proc->timestamp_rx), + rxp, + ru->rx_offset, + ru->nb_rx); + + for (i=0; i<4; i++) { + ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1; + ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2; + } + + ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); +} + + + +void wakeup_gNB_L1s(RU_t *ru) { + int i; + PHY_VARS_gNB **gNB_list = ru->gNB_list; + LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top); + + if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { + // call gNB function directly + char string[20]; + sprintf(string,"Incoming RU %u",ru->idx); + LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx); + ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru); + } else { + LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB); + + for (i=0; inum_gNB; i++) { + LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx); + + if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) { + LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx); + } + } + } +} + +int wakeup_prach_ru(RU_t *ru) { + struct timespec wait; + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) { + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach); + exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + + if (ru->proc.instance_cnt_prach==-1) { + ++ru->proc.instance_cnt_prach; + ru->proc.frame_prach = ru->proc.frame_rx; + ru->proc.subframe_prach = ru->proc.tti_rx; + + // DJP - think prach_procedures() is looking at gNB frame_prach + if (ru->gNB_list[0]) { + ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx; + ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx; + } + + LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx); + // the thread can now be woken up + AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); + } else LOG_W(PHY,"RU prach thread busy, skipping\n"); + + pthread_mutex_unlock( &ru->proc.mutex_prach ); + return(0); +} + +// this is for RU with local RF unit +void fill_rf_config(RU_t *ru, char *rf_config_file) { + int i; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + nfapi_nr_config_request_scf_t *config = &ru->config; //tmp index + openair0_config_t *cfg = &ru->openair0_cfg; + int mu = config->ssb_config.scs_common.value; + int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; + + if (mu == NR_MU_0) { //or if LTE + if(N_RB == 100) { + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + } else if(N_RB == 50) { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } else if (N_RB == 25) { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 2.5e6; + cfg->rx_bw = 2.5e6; + } else if (N_RB == 6) { + cfg->sample_rate=1.92e6; + cfg->samples_per_frame = 19200; + cfg->tx_bw = 1.5e6; + cfg->rx_bw = 1.5e6; + } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB); + } else if (mu == NR_MU_1) { + if(N_RB == 273) { + if (fp->threequarter_fs) { + AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + } else if(N_RB == 217) { + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } + } else if(N_RB == 106) { + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + } else { + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + } + } else if (mu == NR_MU_3) { + if (N_RB == 66) { + cfg->sample_rate = 122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else if(N_RB == 32) { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + } else { + AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); + } + + if (config->cell_config.frame_duplex_type.value==TDD) + cfg->duplex_mode = duplex_mode_TDD; + else //FDD + cfg->duplex_mode = duplex_mode_FDD; + + cfg->Mod_id = 0; + cfg->num_rb_dl=N_RB; + cfg->tx_num_channels=ru->nb_tx; + cfg->rx_num_channels=ru->nb_rx; + + for (i=0; inb_tx; i++) { + if (ru->if_frequency == 0) { + cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; + cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; + } else if (ru->if_freq_offset){ + cfg->tx_freq[i] = (double)(ru->if_frequency); + cfg->rx_freq[i] = (double)(ru->if_frequency + ru->if_freq_offset); + LOG_I(PHY, "Setting IF TX frequency to %lu Hz with IF RX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset); + } else { + cfg->tx_freq[i] = (double)ru->if_frequency; + cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq); + } + cfg->tx_gain[i] = ru->att_tx; + cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; + cfg->configFilename = rf_config_file; + LOG_I(PHY, "Channel %d: setting tx_gain offset %f, rx_gain offset %f, tx_freq %lu Hz, rx_freq %lu Hz\n", + i, cfg->tx_gain[i], + cfg->rx_gain[i], + (unsigned long)cfg->tx_freq[i], + (unsigned long)cfg->rx_freq[i]); + } +} + +/* this function maps the RU tx and rx buffers to the available rf chains. + Each rf chain is is addressed by the card number and the chain on the card. The + rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple + antennas are mapped to successive RF chains on the same card. */ +int setup_RU_buffers(RU_t *ru) { + int i,j; + int card,ant; + //uint16_t N_TA_offset = 0; + NR_DL_FRAME_PARMS *frame_parms; + nfapi_nr_config_request_scf_t *config = &ru->config; + + if (ru) { + frame_parms = ru->nr_frame_parms; + printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + } else { + printf("ru pointer is NULL\n"); + return(-1); + } + int mu = config->ssb_config.scs_common.value; + int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; + + + if (config->cell_config.frame_duplex_type.value == TDD) { + int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 + + double factor=1; + + switch (mu) { + case 0: //15 kHz scs + AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n"); + if (N_RB <= 25) factor = .25; // 7.68 Ms/s + else if (N_RB <=50) factor = .5; // 15.36 Ms/s + else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s + else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s + else AssertFatal(1==0,"Too many PRBS for mu=0\n"); + break; + case 1: //30 kHz sc + AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n"); + if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s + else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s + break; + case 2: //60 kHz scs + AssertFatal(1==0,"scs_common should not be 60 kHz\n"); + break; + case 3: //120 kHz scs + AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n"); + break; + case 4: //240 kHz scs + AssertFatal(1==0,"scs_common should not be 60 kHz\n"); + if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s + else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s + else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); + break; + + if (N_RB == 100) ru->N_TA_offset = 624; + else if (N_RB == 50) ru->N_TA_offset = 624/2; + else if (N_RB == 25) ru->N_TA_offset = 624/4; + } + if (frame_parms->threequarter_fs == 1) factor = factor*.75; + ru->N_TA_offset = (int)(N_TA_offset * factor); + LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor, + config->carrier_config.uplink_frequency.value, N_RB); + } + else ru->N_TA_offset = 0; + + + if (ru->openair0_cfg.mmapped_dma == 1) { + // replace RX signal buffers with mmaped HW versions + for (i=0; inb_rx; i++) { + card = i/4; + ant = i%4; + printf("Mapping RU id %u, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + free(ru->common.rxdata[i]); + ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain+ant]; + printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); + + for (j=0; j<16; j++) { + printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); + ru->common.rxdata[i][j] = 16-j; + } + } + + for (i=0; inb_tx; i++) { + card = i/4; + ant = i%4; + printf("Mapping RU id %u, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + free(ru->common.txdata[i]); + ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant]; + printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); + + for (j=0; j<16; j++) { + printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); + ru->common.txdata[i][j] = 16-j; + } + } + } else { // not memory-mapped DMA + //nothing to do, everything already allocated in lte_init + } + + return(0); +} + +void *ru_stats_thread(void *param) { + RU_t *ru = (RU_t *)param; + wait_sync("ru_stats_thread"); + + while (!oai_exit) { + sleep(1); + + if (opp_enabled == 1) { + + if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); + + if (ru->feptx_ofdm) { + print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL); + print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); + print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); + print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL); + } + + if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); + + print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); + if (ru->fh_north_out) { + print_meas(&ru->compression,"compression",NULL,NULL); + print_meas(&ru->transport,"transport",NULL,NULL); + } + } + } + + return(NULL); +} + +void *ru_thread_tx( void *param ) { + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + PHY_VARS_gNB *gNB; + gNB_L1_proc_t *gNB_proc; + gNB_L1_rxtx_proc_t *L1_proc; + char filename[40]; + int print_frame = 8; + int i = 0; + int ret; + + + wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); + printf( "ru_thread_tx ready\n"); + + while (!oai_exit) { + + LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n"); + // wait until eNBs are finished subframe RX n and TX n+4 + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 ); + wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 ); + + ret = pthread_mutex_lock(&proc->mutex_gNBs); + AssertFatal(ret == 0,"mutex_lock return %d\n",ret); + int frame_tx=proc->frame_tx; + int tti_tx =proc->tti_tx; + uint64_t timestamp_tx = proc->timestamp_tx; + + ret = pthread_mutex_unlock(&proc->mutex_gNBs); + AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + + if (oai_exit) break; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx ); + + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); + + // do OFDM with/without TX front-end processing if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx); + + if(!emulate_rf) { + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx); + + if (ru->fh_north_out) ru->fh_north_out(ru); + } else { + if(proc->frame_tx == print_frame) { + for (i=0; inb_tx; i++) { + + if(proc->tti_tx == 0) { + sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_tx); + LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); + + sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); + LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); + + sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); + LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); + } + + if(proc->tti_tx == 9) { + sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); + LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); + sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); + FILE *output_fd = fopen(filename,"w"); + + if (output_fd) { + fwrite(&ru->common.txdata[i][0], + sizeof(int32_t), + fp->samples_per_frame, + output_fd); + fclose(output_fd); + } else { + LOG_E(PHY,"Cannot write to file %s\n",filename); + } + }//if(proc->tti_tx == 9) + }//for (i=0; inb_tx; i++) + }//if(proc->frame_tx == print_frame) + }//else emulate_rf + + release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs); + + for(i = 0; inum_gNB; i++) { + gNB = ru->gNB_list[i]; + gNB_proc = &gNB->proc; + L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc; + ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx); + AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + + for (int j=0; jnum_RU; j++) { + if (ru == gNB->RU_list[j]) { + if ((gNB_proc->RU_mask_tx&(1< 0) + LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n", + gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx); + + gNB_proc->RU_mask_tx |= (1<RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return + ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); + AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + } else { // all RUs TX are finished so send the ready signal to gNB processing + gNB_proc->RU_mask_tx = 0; + ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); + AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + + ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx); + AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + // the thread can now be woken up + if (L1_proc->instance_cnt_RUs == -1) { + L1_proc->instance_cnt_RUs = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); + AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, + "ERROR pthread_cond_signal for gNB_L1_thread\n"); + } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); + ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); + AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + } + } + } + + release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); + return 0; +} + +void *ru_thread( void *param ) { + static int ru_thread_status; + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = &ru->proc; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + int ret; + int slot = fp->slots_per_frame-1; + int frame = 1023; + char filename[40], threadname[40]; + int print_frame = 8; + int i = 0; + int aa; + + nfapi_nr_config_request_scf_t *cfg = &ru->config; + + // set default return value + ru_thread_status = 0; + // set default return value + sprintf(threadname,"ru_thread %u",ru->idx); + + + LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); + + memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); + + if(emulate_rf) { + fill_rf_config(ru,ru->rf_config_file); + nr_init_frame_parms(&ru->config, fp); + nr_dump_frame_parms(fp); + nr_phy_init_RU(ru); + + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + } else { + // Start IF device if any + if (ru->nr_start_if) { + LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx); + AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n"); + + if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); + else ret = attach_rru(ru); + + AssertFatal(ret==0,"Cannot connect to remote radio\n"); + } + + if (ru->if_south == LOCAL_RF) { // configure RF parameters only + nr_init_frame_parms(&ru->config, fp); + nr_dump_frame_parms(fp); + fill_rf_config(ru,ru->rf_config_file); + nr_phy_init_RU(ru); + ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + AssertFatal(ret==0,"Cannot connect to local radio\n"); + } + + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + } + + sf_ahead = (uint16_t) ceil((float)6/(0x01<numerology_index)); + LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); + pthread_mutex_lock(&RC.ru_mutex); + RC.ru_mask &= ~(1<idx); + pthread_cond_signal(&RC.ru_cond); + pthread_mutex_unlock(&RC.ru_mutex); + wait_sync("ru_thread"); + + if(!emulate_rf) { + // Start RF device if any + if (ru->start_rf) { + if (ru->start_rf(ru) != 0) + LOG_E(HW,"Could not start the RF device\n"); + else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); + + // if an asnych_rxtx thread exists + // wakeup the thread because the devices are ready at this point + + if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) { + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx=0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); + + // if this is a slave RRU, try to synchronize on the DL frequency + if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); + + // start trx write thread + if(usrp_tx_thread == 1){ + if (ru->start_write_thread){ + if(ru->start_write_thread(ru) != 0){ + LOG_E(HW,"Could not start tx write thread\n"); + } + else{ + LOG_I(PHY,"tx write thread ready\n"); + } + } + } + } + + pthread_mutex_lock(&proc->mutex_FH1); + proc->instance_cnt_FH1 = 0; + pthread_mutex_unlock(&proc->mutex_FH1); + pthread_cond_signal(&proc->cond_FH1); + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. + // They are set on the first rx/tx in the underly FH routines. + if (slot==(fp->slots_per_frame-1)) { + slot=0; + frame++; + frame&=1023; + } else { + slot++; + } + + // synchronization on input FH interface, acquire signals/data and block + LOG_D(PHY,"[RU_thread] read data: frame_rx = %d, tti_rx = %d\n", frame, slot); + if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot); + else AssertFatal(1==0, "No fronthaul interface at south port"); + + LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", + frame,slot, + proc->frame_rx,proc->tti_rx, + proc->frame_tx,proc->tti_tx, + RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, + RC.gNB[0]->proc.frame_tx); + /* + LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", + ru->do_prach, + is_prach_subframe(fp, proc->frame_rx, proc->tti_rx), + proc->frame_rx,proc->tti_rx); + + if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) { + wakeup_prach_ru(ru); + }*/ + + // adjust for timing offset between RU + //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx); + if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; + + // do RX front-end processing (frequency-shift, dft) if needed + + int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { + //if (proc->tti_rx==8) { + + if (ru->feprx) { + ru->feprx(ru,proc->tti_rx); + //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); + + LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); + LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); + + for (aa=0;aanb_rx;aa++) + memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa], + (void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); + + // Do PRACH RU processing + + int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); + uint8_t prachStartSymbol,N_dur; + if (prach_id>=0) { + N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt); + /* + get_nr_prach_info_from_index(ru->config.prach_config.prach_ConfigurationIndex.value, + proc->frame_rx,proc->tti_rx, + ru->config.carrier_config.dl_frequency.value, + fp->numerology_index, + fp->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period); + */ + for (int prach_oc = 0; prach_ocprach_list[prach_id].num_prach_ocas; prach_oc++) { + prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol+prach_oc*N_dur; + //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. + + rx_nr_prach_ru(ru, + ru->prach_list[prach_id].fmt, //could also use format + ru->prach_list[prach_id].numRA, + prachStartSymbol, + prach_oc, + proc->frame_rx,proc->tti_rx); + } + free_nr_ru_prach_entry(ru,prach_id); + } + } + } + + // At this point, all information for subframe has been received on FH interface + + // wakeup all gNB processes waiting for this RU + if (ru->num_gNB>0) wakeup_gNB_L1s(ru); + + if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) { + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); + + // do OFDM with/without TX front-end processing if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx); + + if(!emulate_rf) { + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); + + if (ru->fh_north_out) ru->fh_north_out(ru); + } else { + if(proc->frame_tx == print_frame) { + for (i=0; inb_tx; i++) { + sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); + LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1); + + if(proc->tti_tx == 9) { + sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); + LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); + sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); + FILE *output_fd = fopen(filename,"w"); + + if (output_fd) { + fwrite(&ru->common.txdata[i][0], + sizeof(int32_t), + fp->samples_per_frame, + output_fd); + fclose(output_fd); + } else { + LOG_E(PHY,"Cannot write to file %s\n",filename); + } + }//if(proc->tti_tx == 9) + }//for (i=0; inb_tx; i++) + }//if(proc->frame_tx == print_frame) + }//else emulate_rf + + proc->emulate_rf_busy = 0; + }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) + } + + printf( "Exiting ru_thread \n"); + + if (ru->stop_rf != NULL) { + if (ru->stop_rf(ru) != 0) + LOG_E(HW,"Could not stop the RF device\n"); + else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); + } + + ru_thread_status = 0; + return &ru_thread_status; +} +/* +// This thread run the initial synchronization like a UE +void *ru_thread_synch(void *arg) { + + RU_t *ru = (RU_t*)arg; + NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; + int32_t sync_pos,sync_pos2; + uint32_t peak_val; + uint32_t sync_corr[307200] __attribute__((aligned(32))); + static int ru_thread_synch_status; + + + + wait_sync("ru_thread_synch"); + + // initialize variables for PSS detection + lte_sync_time_init(ru->nr_frame_parms); + + while (!oai_exit) { + + // wait to be woken up + if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break; + + // if we're not in synch, then run initial synch + if (ru->in_synch == 0) { + // run intial synch like UE + LOG_I(PHY,"Running initial synchronization\n"); + + sync_pos = lte_sync_time_gNB(ru->common.rxdata, + fp, + fp->samples_per_subframe*5, + &peak_val, + sync_corr); + LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val); + + if (sync_pos >= 0) { + if (sync_pos >= fp->nb_prefix_samples) + sync_pos2 = sync_pos - fp->nb_prefix_samples; + else + sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples; + + if (fp->frame_type == FDD) { + + // PSS is hypothesized in last symbol of first slot in Frame + int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples; + + if (sync_pos2 >= sync_pos_slot) + ru->rx_offset = sync_pos2 - sync_pos_slot; + else + ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot; + } + else { + + } + + LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset); + + if ((peak_val > 300000) && (sync_pos > 0)) { + // if (sync_pos++ > 3) { + write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2); + write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1); + exit(-1); + } + + ru->in_synch=1; + } + } + + if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break; + } // oai_exit + + ru_thread_synch_status = 0; + return &ru_thread_synch_status; + +} +*/ + +int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) { + return(ru->ifdevice.trx_start_func(&ru->ifdevice)); +} + +int start_rf(RU_t *ru) { + return(ru->rfdevice.trx_start_func(&ru->rfdevice)); +} + +int stop_rf(RU_t *ru) { + ru->rfdevice.trx_end_func(&ru->rfdevice); + return 0; +} + +int start_write_thread(RU_t *ru) { + return(ru->rfdevice.trx_write_init(&ru->rfdevice)); +} + +void init_RU_proc(RU_t *ru) { + int i=0; + RU_proc_t *proc; + char name[100]; + LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); + proc = &ru->proc; + memset((void *)proc,0,sizeof(RU_proc_t)); + proc->ru = ru; + proc->instance_cnt_prach = -1; + proc->instance_cnt_synch = -1; + proc->instance_cnt_FH = -1; + proc->instance_cnt_FH1 = -1; + proc->instance_cnt_gNBs = -1; + proc->instance_cnt_asynch_rxtx = -1; + proc->instance_cnt_emulateRF = -1; + proc->first_rx = 1; + proc->first_tx = 1; + proc->frame_offset = 0; + proc->num_slaves = 0; + proc->frame_tx_unwrap = 0; + proc->feptx_mask = 0; + + for (i=0; i<10; i++) proc->symbol_mask[i]=0; + + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); + pthread_mutex_init( &proc->mutex_synch,NULL); + pthread_mutex_init( &proc->mutex_FH,NULL); + pthread_mutex_init( &proc->mutex_FH1,NULL); + pthread_mutex_init( &proc->mutex_emulateRF,NULL); + pthread_mutex_init( &proc->mutex_gNBs, NULL); + pthread_cond_init( &proc->cond_prach, NULL); + pthread_cond_init( &proc->cond_FH, NULL); + pthread_cond_init( &proc->cond_FH1, NULL); + pthread_cond_init( &proc->cond_emulateRF, NULL); + pthread_cond_init( &proc->cond_asynch_rxtx, NULL); + pthread_cond_init( &proc->cond_synch,NULL); + pthread_cond_init( &proc->cond_gNBs, NULL); + threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX ); + + if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) + threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT ); + + if(emulate_rf) + threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); + + if (ru->function == NGFI_RRU_IF4p5) { + threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT ); + ///tmp deactivation of synch thread + // if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); + + if ((ru->if_timing == synch_to_other) || + (ru->function == NGFI_RRU_IF5) || + (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT ); + + snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); + pthread_setname_np( proc->pthread_FH, name ); + } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF + LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); + threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT ); + } + + if (get_thread_worker_conf() == WORKER_ENABLE) { + if (ru->feprx) nr_init_feprx_thread(ru); + + if (ru->feptx_ofdm) nr_init_feptx_thread(ru); + } + + if (opp_enabled == 1) threadCreate(&ru->ru_stats_thread,ru_stats_thread,(void *)ru, "emulateRF", -1, OAI_PRIORITY_RT_LOW); +} + +void kill_NR_RU_proc(int inst) { + RU_t *ru = RC.ru[inst]; + RU_proc_t *proc = &ru->proc; + pthread_mutex_lock(&proc->mutex_FH); + proc->instance_cnt_FH = 0; + pthread_mutex_unlock(&proc->mutex_FH); + pthread_cond_signal(&proc->cond_FH); + pthread_mutex_lock(&proc->mutex_prach); + proc->instance_cnt_prach = 0; + pthread_mutex_unlock(&proc->mutex_prach); + pthread_cond_signal(&proc->cond_prach); + pthread_mutex_lock(&proc->mutex_synch); + proc->instance_cnt_synch = 0; + pthread_mutex_unlock(&proc->mutex_synch); + pthread_cond_signal(&proc->cond_synch); + pthread_mutex_lock(&proc->mutex_gNBs); + proc->instance_cnt_gNBs = 0; + pthread_mutex_unlock(&proc->mutex_gNBs); + pthread_cond_signal(&proc->cond_gNBs); + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx = 0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + LOG_D(PHY, "Joining pthread_FH\n"); + pthread_join(proc->pthread_FH, NULL); + + if (ru->function == NGFI_RRU_IF4p5) { + LOG_D(PHY, "Joining pthread_prach\n"); + pthread_join(proc->pthread_prach, NULL); + + if (ru->is_slave) { + LOG_D(PHY, "Joining pthread_\n"); + pthread_join(proc->pthread_synch, NULL); + } + + if ((ru->if_timing == synch_to_other) || + (ru->function == NGFI_RRU_IF5) || + (ru->function == NGFI_RRU_IF4p5)) { + LOG_D(PHY, "Joining pthread_asynch_rxtx\n"); + pthread_join(proc->pthread_asynch_rxtx, NULL); + } + } + + if (get_nprocs() >= 2) { + if (ru->feprx) { + pthread_mutex_lock(&proc->mutex_fep); + proc->instance_cnt_fep = 0; + pthread_mutex_unlock(&proc->mutex_fep); + pthread_cond_signal(&proc->cond_fep); + LOG_D(PHY, "Joining pthread_fep\n"); + pthread_join(proc->pthread_fep, NULL); + pthread_mutex_destroy(&proc->mutex_fep); + pthread_cond_destroy(&proc->cond_fep); + } + + if (ru->feptx_ofdm) { + pthread_mutex_lock(&proc->mutex_feptx); + proc->instance_cnt_feptx = 0; + pthread_mutex_unlock(&proc->mutex_feptx); + pthread_cond_signal(&proc->cond_feptx); + LOG_D(PHY, "Joining pthread_feptx\n"); + pthread_join(proc->pthread_feptx, NULL); + pthread_mutex_destroy(&proc->mutex_feptx); + pthread_cond_destroy(&proc->cond_feptx); + } + } + + if (opp_enabled) { + LOG_D(PHY, "Joining ru_stats_thread\n"); + pthread_join(ru->ru_stats_thread, NULL); + } + + pthread_mutex_destroy(&proc->mutex_prach); + pthread_mutex_destroy(&proc->mutex_asynch_rxtx); + pthread_mutex_destroy(&proc->mutex_synch); + pthread_mutex_destroy(&proc->mutex_FH); + pthread_mutex_destroy(&proc->mutex_gNBs); + pthread_cond_destroy(&proc->cond_prach); + pthread_cond_destroy(&proc->cond_FH); + pthread_cond_destroy(&proc->cond_asynch_rxtx); + pthread_cond_destroy(&proc->cond_synch); + pthread_cond_destroy(&proc->cond_gNBs); +} + +int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) +{ + FH_fmt_options_t fmt = cap->FH_fmt; + int i; + int found_band=0; + LOG_I(PHY,"RRU %d, num_bands %d, looking for band %d\n",ru->idx,cap->num_bands,ru->nr_frame_parms->nr_band); + + for (i=0; inum_bands; i++) { + LOG_I(PHY,"band %d on RRU %d\n",cap->band_list[i],ru->idx); + + if (ru->nr_frame_parms->nr_band == cap->band_list[i]) { + found_band=1; + break; + } + } + + if (found_band == 0) { + LOG_I(PHY,"Couldn't find target NR band %d on RRU %d\n",ru->nr_frame_parms->nr_band,ru->idx); + return(-1); + } + + switch (ru->if_south) { + case LOCAL_RF: + AssertFatal(1==0, "This RU should not have a local RF, exiting\n"); + return(0); + break; + + case REMOTE_IF5: + if (fmt == OAI_IF5_only || fmt == OAI_IF5_and_IF4p5) return(0); + + break; + + case REMOTE_IF4p5: + if (fmt == OAI_IF4p5_only || fmt == OAI_IF5_and_IF4p5) return(0); + + break; + + case REMOTE_MBP_IF5: + if (fmt == MBP_IF5) return(0); + + break; + + default: + LOG_I(PHY,"No compatible Fronthaul interface found for RRU %d\n", ru->idx); + return(-1); + } + + return(-1); +} + + +char rru_format_options[4][20] = {"OAI_IF5_only","OAI_IF4p5_only","OAI_IF5_and_IF4p5","MBP_IF5"}; + +char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"}; +char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"}; + +void configure_ru(int idx, + void *arg) +{ + RU_t *ru = RC.ru[idx]; + RRU_config_t *config = (RRU_config_t *)arg; + RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg; + nfapi_nr_config_request_scf_t *cfg = &ru->config; + int ret; + LOG_I(PHY, "Received capabilities from RRU %d\n",idx); + + if (capabilities->FH_fmt < MAX_FH_FMTs) LOG_I(PHY, "RU FH options %s\n",rru_format_options[capabilities->FH_fmt]); + + ret = check_capabilities(ru,capabilities); + AssertFatal(ret == 0, "Cannot configure RRU %d, check_capabilities returned %d\n", idx, ret); + // take antenna capabilities of RRU + ru->nb_tx = capabilities->nb_tx[0]; + ru->nb_rx = capabilities->nb_rx[0]; + // Pass configuration to RRU + LOG_I(PHY, "Using %s fronthaul (%d), band %d \n",ru_if_formats[ru->if_south],ru->if_south,ru->nr_frame_parms->nr_band); + // wait for configuration + config->FH_fmt = ru->if_south; + config->num_bands = 1; + config->band_list[0] = ru->nr_frame_parms->nr_band; + config->tx_freq[0] = ru->nr_frame_parms->dl_CarrierFreq; + config->rx_freq[0] = ru->nr_frame_parms->ul_CarrierFreq; + //config->tdd_config[0] = ru->nr_frame_parms->tdd_config; + //config->tdd_config_S[0] = ru->nr_frame_parms->tdd_config_S; + config->att_tx[0] = ru->att_tx; + config->att_rx[0] = ru->att_rx; + config->N_RB_DL[0] = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value; + config->N_RB_UL[0] = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value; + config->threequarter_fs[0] = ru->nr_frame_parms->threequarter_fs; + /* if (ru->if_south==REMOTE_IF4p5) { + config->prach_FreqOffset[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset; + config->prach_ConfigIndex[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; + LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n", + config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);*/ + nr_init_frame_parms(&ru->config, ru->nr_frame_parms); + nr_phy_init_RU(ru); +} + +void configure_rru(int idx, + void *arg) { + RRU_config_t *config = (RRU_config_t *)arg; + RU_t *ru = RC.ru[idx]; + nfapi_nr_config_request_scf_t *cfg = &ru->config; + ru->nr_frame_parms->nr_band = config->band_list[0]; + ru->nr_frame_parms->dl_CarrierFreq = config->tx_freq[0]; + ru->nr_frame_parms->ul_CarrierFreq = config->rx_freq[0]; + + if (ru->nr_frame_parms->dl_CarrierFreq == ru->nr_frame_parms->ul_CarrierFreq) { + cfg->cell_config.frame_duplex_type.value = TDD; + //ru->nr_frame_parms->tdd_config = config->tdd_config[0]; + //ru->nr_frame_parms->tdd_config_S = config->tdd_config_S[0]; + } else + cfg->cell_config.frame_duplex_type.value = FDD; + + ru->att_tx = config->att_tx[0]; + ru->att_rx = config->att_rx[0]; + int mu = cfg->ssb_config.scs_common.value; + cfg->carrier_config.dl_grid_size[mu].value = config->N_RB_DL[0]; + cfg->carrier_config.dl_grid_size[mu].value = config->N_RB_UL[0]; + ru->nr_frame_parms->threequarter_fs = config->threequarter_fs[0]; + + //ru->nr_frame_parms->pdsch_config_common.referenceSignalPower = ru->max_pdschReferenceSignalPower-config->att_tx[0]; + if (ru->function==NGFI_RRU_IF4p5) { + ru->nr_frame_parms->att_rx = ru->att_rx; + ru->nr_frame_parms->att_tx = ru->att_tx; + /* + LOG_I(PHY,"Setting ru->function to NGFI_RRU_IF4p5, prach_FrequOffset %d, prach_ConfigIndex %d, att (%d,%d)\n", + config->prach_FreqOffset[0],config->prach_ConfigIndex[0],ru->att_tx,ru->att_rx); + ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0]; + ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0]; */ + } + + fill_rf_config(ru,ru->rf_config_file); + nr_init_frame_parms(&ru->config, ru->nr_frame_parms); + nr_phy_init_RU(ru); +} + +/* +void init_precoding_weights(PHY_VARS_gNB *gNB) { + + int layer,ru_id,aa,re,ue,tb; + LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms; + RU_t *ru; + LTE_gNB_DLSCH_t *dlsch; + + // init precoding weigths + for (ue=0;uedlsch[ue][tb]; + for (layer=0; layer<4; layer++) { + int nb_tx=0; + for (ru_id=0;ru_idnb_tx; + } + dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(nb_tx*sizeof(int32_t*)); + + for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); + for (re=0;reofdm_symbol_size; re++) { + dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; + } + } + } + } + } +}*/ + +void set_function_spec_param(RU_t *ru) { + int ret; + + switch (ru->if_south) { + case LOCAL_RF: // this is an RU with integrated RF (RRU, gNB) + if (ru->function == NGFI_RRU_IF5) { // IF5 RRU + ru->do_prach = 0; // no prach processing in RU + ru->fh_north_in = NULL; // no shynchronous incoming fronthaul from north + ru->fh_north_out = fh_if5_north_out; // need only to do send_IF5 reception + ru->fh_south_out = tx_rf; // send output to RF + ru->fh_north_asynch_in = fh_if5_north_asynch_in; // TX packets come asynchronously + ru->feprx = NULL; // nothing (this is a time-domain signal) + ru->feptx_ofdm = NULL; // nothing (this is a time-domain signal) + ru->feptx_prec = NULL; // nothing (this is a time-domain signal) + ru->nr_start_if = nr_start_if; // need to start the if interface for if5 + ru->ifdevice.host_type = RRU_HOST; + ru->rfdevice.host_type = RRU_HOST; + ru->ifdevice.eth_params = &ru->eth_params; + reset_meas(&ru->rx_fhaul); + reset_meas(&ru->tx_fhaul); + reset_meas(&ru->compression); + reset_meas(&ru->transport); + ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); + printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); + + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + } else if (ru->function == NGFI_RRU_IF4p5) { + ru->do_prach = 1; // do part of prach processing in RU + ru->fh_north_in = NULL; // no synchronous incoming fronthaul from north + ru->fh_north_out = fh_if4p5_north_out; // send_IF4p5 on reception + ru->fh_south_out = tx_rf; // send output to RF + ru->fh_north_asynch_in = fh_if4p5_north_asynch_in; // TX packets come asynchronously + ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // RX DFTs + ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft only (no precoding in RRU) + ru->feptx_prec = NULL; + ru->nr_start_if = nr_start_if; // need to start the if interface for if4p5 + ru->ifdevice.host_type = RRU_HOST; + ru->rfdevice.host_type = RRU_HOST; + ru->ifdevice.eth_params = &ru->eth_params; + reset_meas(&ru->rx_fhaul); + reset_meas(&ru->tx_fhaul); + reset_meas(&ru->compression); + reset_meas(&ru->transport); + ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); + printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); + + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + + malloc_IF4p5_buffer(ru); + } else if (ru->function == gNodeB_3GPP) { + ru->do_prach = 0; // no prach processing in RU + ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // RX DFTs + ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft and precoding + ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // this is fep with idft and precoding + ru->fh_north_in = NULL; // no incoming fronthaul from north + ru->fh_north_out = NULL; // no outgoing fronthaul to north + ru->nr_start_if = NULL; // no if interface + ru->rfdevice.host_type = RAU_HOST; + + // FK this here looks messed up. The following lines should be part of the if (ru->function == gNodeB_3GPP), shouldn't they? + + ru->fh_south_in = rx_rf; // local synchronous RF RX + ru->fh_south_out = tx_rf; // local synchronous RF TX + ru->start_rf = start_rf; // need to start the local RF interface + ru->stop_rf = stop_rf; + ru->start_write_thread = start_write_thread; // starting RF TX in different thread + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); + } + + /* + printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); + fill_rf_config(ru,rf_config_file); + init_frame_parms(&ru->frame_parms,1); + nr_phy_init_RU(ru); + + ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + */ + break; + + case REMOTE_IF5: // the remote unit is IF5 RRU + ru->do_prach = 0; + ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // this is frequency-shift + DFTs + ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // need to do transmit Precoding + IDFTs + ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // need to do transmit Precoding + IDFTs + ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception + ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission + ru->fh_south_asynch_in = NULL; // no asynchronous UL + ru->start_rf = NULL; // no local RF + ru->stop_rf = NULL; + ru->start_write_thread = NULL; + ru->nr_start_if = nr_start_if; // need to start if interface for IF5 + ru->ifdevice.host_type = RAU_HOST; + ru->ifdevice.eth_params = &ru->eth_params; + ru->ifdevice.configure_rru = configure_ru; + ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); + printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); + + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + + break; + + case REMOTE_IF4p5: + ru->do_prach = 0; + ru->feprx = NULL; // DFTs + ru->feptx_prec = nr_feptx_prec; // Precoding operation + ru->feptx_ofdm = NULL; // no OFDM mod + ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception + ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission + ru->fh_south_asynch_in = (ru->if_timing == synch_to_other) ? fh_if4p5_south_in : NULL; // asynchronous UL if synch_to_other + ru->fh_north_out = NULL; + ru->fh_north_asynch_in = NULL; + ru->start_rf = NULL; // no local RF + ru->stop_rf = NULL; + ru->start_write_thread = NULL; + ru->nr_start_if = nr_start_if; // need to start if interface for IF4p5 + ru->ifdevice.host_type = RAU_HOST; + ru->ifdevice.eth_params = &ru->eth_params; + ru->ifdevice.configure_rru = configure_ru; + ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params); + printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); + + if (ret<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + + if (ru->ifdevice.get_internal_parameter != NULL) { + void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in"); + if (t != NULL) + ru->fh_south_in = t; + t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out"); + if (t != NULL) + ru->fh_south_out = t; + } + + malloc_IF4p5_buffer(ru); + break; + + default: + LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); + break; + } // switch on interface type +} + +void init_NR_RU(char *rf_config_file) +{ + int ru_id; + RU_t *ru; + PHY_VARS_gNB *gNB_RC; + PHY_VARS_gNB *gNB0= (PHY_VARS_gNB *)NULL; + NR_DL_FRAME_PARMS *fp = (NR_DL_FRAME_PARMS *)NULL; + int i; + // create status mask + RC.ru_mask = 0; + pthread_mutex_init(&RC.ru_mutex,NULL); + pthread_cond_init(&RC.ru_cond,NULL); + // read in configuration file) + printf("configuring RU from file\n"); + RCconfig_RU(); + LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs()); + + LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); + + for (ru_id=0; ru_idrf_config_file = rf_config_file; + ru->idx = ru_id; + ru->ts_offset = 0; + // use gNB_list[0] as a reference for RU frame parameters + // NOTE: multiple CC_id are not handled here yet! + + if (ru->num_gNB > 0) { + LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p RC.gNB[0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], RC.gNB[0], ru->rf_config_file); + + if (ru->gNB_list[0] == 0) { + LOG_E(PHY,"%s() DJP - ru->gNB_list ru->num_gNB are not initialized - so do it manually\n", __FUNCTION__); + ru->gNB_list[0] = RC.gNB[0]; + ru->num_gNB=1; + // + // DJP - feptx_prec() / feptx_ofdm() parses the gNB_list (based on num_gNB) and copies the txdata_F to txdata in RU + // + } else { + LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__); + } + } + + gNB_RC = RC.gNB[0]; + gNB0 = ru->gNB_list[0]; + fp = ru->nr_frame_parms; + LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south); + + if (gNB0) { + if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5)) + AssertFatal(gNB0!=NULL,"gNB0 is null!\n"); + + if (gNB0 && gNB_RC) { + LOG_I(PHY,"Copying frame parms from gNB in RC to gNB %d in ru %d and frame_parms in ru\n",gNB0->Mod_id,ru->idx); + memset((void *)fp, 0, sizeof(NR_DL_FRAME_PARMS)); + memcpy((void *)fp,&gNB_RC->frame_parms,sizeof(NR_DL_FRAME_PARMS)); + memcpy((void *)&gNB0->frame_parms,(void *)&gNB_RC->frame_parms,sizeof(NR_DL_FRAME_PARMS)); + // attach all RU to all gNBs in its list/ + LOG_D(PHY,"ru->num_gNB:%d gNB0->num_RU:%d\n", ru->num_gNB, gNB0->num_RU); + + for (i=0; inum_gNB; i++) { + gNB0 = ru->gNB_list[i]; + gNB0->RU_list[gNB0->num_RU++] = ru; + } + } + } + + //LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],NB_timing[ru->if_timing],ru->function); + set_function_spec_param(ru); + LOG_I(PHY,"Starting ru_thread %d\n",ru_id); + init_RU_proc(ru); + } // for ru_id + + // sleep(1); + LOG_D(HW,"[nr-softmodem.c] RU threads created\n"); +} + + +void stop_RU(int nb_ru) +{ + for (int inst = 0; inst < nb_ru; inst++) { + LOG_I(PHY, "Stopping RU %d processing threads\n", inst); + kill_NR_RU_proc(inst); + } +} + + +/* --------------------------------------------------------*/ +/* from here function to use configuration module */ +void RCconfig_RU(void) +{ + int i = 0, j = 0; + paramdef_t RUParams[] = RUPARAMS_DESC; + paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; + config_getlist( &RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL); + + if ( RUParamList.numelt > 0) { + RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); + RC.ru_mask=(1<idx = j; + RC.ru[j]->nr_frame_parms = (NR_DL_FRAME_PARMS *)malloc(sizeof(NR_DL_FRAME_PARMS)); + RC.ru[j]->frame_parms = (LTE_DL_FRAME_PARMS *)malloc(sizeof(LTE_DL_FRAME_PARMS)); + printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]); + RC.ru[j]->if_timing = synch_to_ext_device; + + if (RC.nb_nr_L1_inst >0) + RC.ru[j]->num_gNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt; + else + 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]]; + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { + RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); + } + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { + RC.ru[j]->openair0_cfg.clock_source = internal; + LOG_D(PHY, "RU clock source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { + RC.ru[j]->openair0_cfg.clock_source = external; + LOG_D(PHY, "RU clock source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.clock_source = gpsdo; + LOG_D(PHY, "RU clock source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } + else { + RC.ru[j]->openair0_cfg.clock_source = unset; + } + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { + RC.ru[j]->openair0_cfg.time_source = internal; + LOG_D(PHY, "RU time source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { + RC.ru[j]->openair0_cfg.time_source = external; + LOG_D(PHY, "RU time source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.time_source = gpsdo; + LOG_D(PHY, "RU time source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } + else { + RC.ru[j]->openair0_cfg.time_source = unset; + } + + if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { + if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = gNodeB_3GPP; + printf("Setting function for RU %d to gNodeB_3GPP\n",j); + } else { + RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); + + if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = NGFI_RRU_IF5; + RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; + printf("Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j); + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = NGFI_RRU_IF5; + RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; + printf("Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j); + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = NGFI_RRU_IF4p5; + RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + printf("Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j); + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = NGFI_RRU_IF4p5; + RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j); + } + } + + RC.ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; + RC.ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); + RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; + + for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; + } //strcmp(local_rf, "yes") == 0 + else { + printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); + RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); + + if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { + RC.ru[j]->if_south = REMOTE_IF5; + RC.ru[j]->function = NGFI_RAU_IF5; + RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { + RC.ru[j]->if_south = REMOTE_IF5; + RC.ru[j]->function = NGFI_RAU_IF5; + RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { + RC.ru[j]->if_south = REMOTE_IF4p5; + RC.ru[j]->function = NGFI_RAU_IF4p5; + RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { + RC.ru[j]->if_south = REMOTE_IF4p5; + RC.ru[j]->function = NGFI_RAU_IF4p5; + RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + } + } /* strcmp(local_rf, "yes") != 0 */ + + RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); + RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); + RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); + RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); + RC.ru[j]->if_frequency = *(RUParamList.paramarray[j][RU_IF_FREQUENCY].u64ptr); + RC.ru[j]->if_freq_offset = *(RUParamList.paramarray[j][RU_IF_FREQ_OFFSET].iptr); + + if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) { + RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt; + for (i=0; inum_gNB; i++) { + RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t)); + for (int b=0; bnb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b]; + } + } + }// j=0..num_rus + } else { + RC.nb_RU = 0; + } // setting != NULL + + return; +} + diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 4ca02ed929..20db37b123 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1242,6 +1242,8 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu=&dl_tti_pdu_list[i]; memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); int SFN=sfn+2; + //if(!&dl_tti_pdu->pdcch_pdu) + printf("interleaversize = %d, coreset_type = %d. \n",dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize,dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15.CoreSetType); handle_nfapi_nr_pdcch_pdu(gNB, SFN, slot, &dl_tti_pdu->pdcch_pdu); //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 837f33fe6f..8b1060f691 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -277,9 +277,9 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); - + pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)) return 0; + } // TODO: resolve the packaging of array (currently sending a single element) @@ -307,6 +307,7 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + printf("packing pdsch pdu. \n"); nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; // TODO: resolve the packaging of array (currently sending a single element) @@ -360,6 +361,7 @@ static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + printf("Packing ssb. \n"); nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; return( @@ -909,7 +911,7 @@ static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_ //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) )) return 0; - + int arr[12]; for(int i=0;idl_tti_request_body.nGroup;i++) { @@ -3394,6 +3396,7 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + printf("result of pack dl_tti_req is %d. \n",result); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: @@ -3749,7 +3752,7 @@ static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppReadP static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ +{ nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) @@ -3765,7 +3768,7 @@ static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)); + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)) return 0; } @@ -3847,7 +3850,8 @@ static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ +{ + printf("ssb received and unpacked. \n"); nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; return( diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 18891cdee9..fa919ac3a5 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1495,7 +1495,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, { uint32_t recv_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); uint32_t current_sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); - printf("p7_msg_sfn: %d, p7_msg_slot: %d, phy_sfn:%d , phy_slot:%d \n",sfn,slot,phy->sfn,phy->slot); + //printf("p7_msg_sfn: %d, p7_msg_slot: %d, phy_sfn:%d , phy_slot:%d \n",sfn,slot,phy->sfn,phy->slot); uint8_t in_window = 0; uint8_t timing_window = phy->_public.slot_buffer_size; @@ -1630,7 +1630,6 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_dl_tti_request structure\n"); return; } - int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_dl_tti_request_t), &(pnf_p7->_public.codec_config)); if(unpack_result == 0) @@ -2989,13 +2988,11 @@ void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_tim struct sockaddr_in remote_addr; socklen_t remote_addr_size = sizeof(remote_addr); remote_addr.sin_family = 2; //hardcoded - do { // peek the header uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH]; recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); - if(recvfrom_result > 0) { // get the segment size diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index ffbc5819bc..8edb168e38 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -533,6 +533,7 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); + //printf("segment %d \n", segment); } } else diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 05d6c4c112..384ab5c9b5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -32,6 +32,7 @@ */ #include "nr_dlsch.h" +#include "../../../nfapi/oai_integration/vendor_ext.h" extern void set_taus_seed(unsigned int seed_type); @@ -263,13 +264,21 @@ int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { for (i=0; idlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i); AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i); - LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, - gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); + //LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, + //gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); + LOG_D(PHY,"searching for harq_mask %x, rnti %x, gNB->dlsch[i][0]->rnti %x\n", gNB->dlsch[i][0]->harq_mask, rnti, gNB->dlsch[i][0]->rnti); if ((gNB->dlsch[i][0]->harq_mask >0) && (gNB->dlsch[i][0]->rnti==rnti)) return i; - else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; + else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) { + //printf("gNB->dlsch[i][0]->harq_mask = %d \n", gNB->dlsch[i][0]->harq_mask);; + first_free_index=i; + } + + } + if (type == SEARCH_EXIST) { + printf("type = %d \n", type); + return -1; } - if (type == SEARCH_EXIST) return -1; if (first_free_index != -1) gNB->dlsch[first_free_index][0]->rnti = 0; return first_free_index; @@ -284,7 +293,10 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB, uint8_t *sdu) { nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &pdsch_pdu->pdsch_pdu_rel15; - + if (NFAPI_MODE == NFAPI_MODE_PNF) { + gNB->dlsch[0][0]->harq_mask = 1; + gNB->dlsch[0][0]->rnti = 4660; + } int dlsch_id = find_nr_dlsch(rel15->rnti,gNB,SEARCH_EXIST); AssertFatal( (dlsch_id>=0) && (dlsch_idrnti,dlsch_id); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 429bd9a836..18ab627392 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -577,7 +577,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); + LOG_I(PHY,"Segment %u CRC OK\n\033[0m",r); if (r==0) { for (int i=0;i<10;i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t*)llrProcBuf)[i]); } @@ -587,7 +587,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, ret = no_iteration_ldpc; } else { - LOG_D(PHY,"CRC NOT OK\n\033[0m"); + LOG_I(PHY,"CRC NOT OK\n\033[0m"); ret = 1 + dlsch->max_ldpc_iterations; } diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index d65d3b54bb..15c2a5c988 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -104,8 +104,6 @@ void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, nr_fill_dci(gNB,frame,slot,pdcch_pdu); - - } void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, @@ -182,26 +180,30 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - if(NFAPI_MODE != NFAPI_MODE_VNF) + if(NFAPI_MODE != NFAPI_MODE_VNF){ + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); handle_nfapi_nr_pdcch_pdu(gNB, frame, slot, &dl_tti_pdu->pdcch_pdu); - + } pdcch_received = 1; break; case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + LOG_I(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - if(NFAPI_MODE != NFAPI_MODE_VNF) + if(NFAPI_MODE != NFAPI_MODE_VNF){ + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); + } } } } @@ -232,15 +234,15 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ } } - if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) - { - oai_nfapi_ul_tti_req(UL_tti_req); - } + // if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) + // { + // oai_nfapi_ul_tti_req(UL_tti_req); + // } - if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) - { - oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); - } + // if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) + // { + // oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); + // } if (NFAPI_MODE != NFAPI_MONOLITHIC) { @@ -248,6 +250,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ { Sched_INFO->DL_req->SFN = frame; Sched_INFO->DL_req->Slot = slot; + printf("DL tti Frame = %d, slot = %d. \n",frame,slot); oai_nfapi_dl_tti_req(Sched_INFO->DL_req); } if (Sched_INFO->TX_req->Number_of_PDUs > 0) diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 3864b2fcb2..d3b8c77eed 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -315,7 +315,7 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot if (cfg->cell_config.frame_duplex_type.value == FDD) { return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT ); } - + if (nr_frame%2 == 0) { for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index f775eb9130..55626e386e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -547,6 +547,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); if (gNB->frame_parms.frame_type == TDD) + if(NFAPI_MODE != NFAPI_MODE_VNF) fill_ul_rb_mask(gNB, frame_rx, slot_rx); gNB_I0_measurements(gNB); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index e70c353589..bdbfae58e3 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -121,6 +121,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); + dlsch0_harq->status = ACTIVE; //Gokul if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 7201b29596..e356afb339 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -104,7 +104,10 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; gNB->pdu_index[CC_idP] = 0; - + if (NFAPI_MODE == NFAPI_MODE_VNF) + { + memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); + } if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { // monolithic or PNF DL_req[CC_idP].SFN = frameP; @@ -303,14 +306,13 @@ bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_t slot){ - + gNB_MAC_INST *mac = RC.nrmac[module_idP]; + nfapi_nr_config_request_scf_t *cfg = &mac->config[0]; protocol_ctxt_t ctxt; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); - int nb_periods_per_frame; const int bwp_id = 1; - gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -356,7 +358,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, int num_slots_per_tdd = (nr_slots_per_frame[*scc->ssbSubcarrierSpacing])/nb_periods_per_frame; const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0); - start_meas(&RC.nrmac[module_idP]->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN); @@ -387,9 +388,10 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // clear last scheduled slot's content (only)! const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; const int last_slot = (slot + num_slots - 1) % num_slots; + const int two_slots_back = (slot + num_slots - 2) % num_slots; uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); - + memset(&vrb_map_UL[two_slots_back * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); } @@ -434,15 +436,19 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedules the DCI for Uplink and subsequently PUSCH { - nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); + if(NFAPI_MODE == NFAPI_MODE_VNF){ + gNB->UL_tti_req_ahead[0][7].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 + gNB->UL_tti_req_ahead[0][8].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 + gNB->UL_tti_req_ahead[0][9].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 + gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; + } + //nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); } - // This schedules the DCI for Downlink and PDSCH if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot)) nr_schedule_ue_spec(module_idP, frame, slot); - - nr_schedule_pucch(module_idP, frame, slot); + //nr_schedule_pucch(module_idP, frame, slot); stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 4d491b2843..92cb65aa57 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -47,6 +47,7 @@ /*Softmodem params*/ #include "executables/softmodem-common.h" +#include "../../../nfapi/oai_integration/vendor_ext.h" //////////////////////////////////////////////////////// /////* DLSCH MAC PDU generation (6.1.2 TS 38.321) *///// @@ -651,7 +652,7 @@ void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, sub_frame_t slot) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; - + /* PREPROCESSOR */ gNB_mac->pre_processor_dl(module_id, frame, slot); @@ -716,6 +717,8 @@ void nr_schedule_ue_spec(module_id_t module_id, int8_t current_harq_pid = sched_ctrl->dl_harq_pid; if (current_harq_pid < 0) { /* PP has not selected a specific HARQ Process, get a new one */ + if (NFAPI_MODE == NFAPI_MODE_VNF) + sched_ctrl->available_dl_harq.head = 0; current_harq_pid = sched_ctrl->available_dl_harq.head; AssertFatal(current_harq_pid >= 0, "no free HARQ process available for UE %d\n", @@ -732,6 +735,9 @@ void nr_schedule_ue_spec(module_id_t module_id, remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; + if (NFAPI_MODE == NFAPI_MODE_VNF) { + harq->is_waiting = false; + } DevAssert(!harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0]; @@ -765,7 +771,15 @@ void nr_schedule_ue_spec(module_id_t module_id, const int bwpid = sched_ctrl->active_bwp->bwp_Id; const int coresetid = sched_ctrl->coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; + //nfapi_nr_dl_tti_pdcch_pdu_rel15_t temp; + // if(NFAPI_MODE == NFAPI_MODE_VNF){ + // memcpy(temp,gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid],sizeof(nfapi_nr_dl_tti_pdcch_pdu_rel15_t)); + // pdcch_pdu = temp; + + // } + if (!pdcch_pdu) { + printf("creating pdcch pdu, pdcch_pdu = NULL. \n"); nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 20da8fa30a..e7149c5d65 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1666,6 +1666,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secon const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig->pdsch_ServingCellConfig->choice.setup; const int nrofHARQ = pdsch->nrofHARQ_ProcessesForPDSCH ? get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8; + printf("nrofHARQ = %d\n", nrofHARQ); // add all available DL HARQ processes for this UE create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ); for (int harq = 0; harq < nrofHARQ; harq++) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 629b4dc7b0..9e3a611356 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -235,6 +235,8 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[2]; + if(NFAPI_MODE == NFAPI_MODE_VNF) + curr_pucch->csi_bits = 0; AssertFatal(curr_pucch->csi_bits == 0 && !curr_pucch->sr_flag && curr_pucch->dai_c == 0, @@ -458,11 +460,19 @@ bool nr_acknack_scheduling(int mod_id, "illegal number of bits in PUCCH of UE %d\n", UE_id); /* if the currently allocated PUCCH of this UE is full, allocate it */ + pucch->sr_flag = 1; pucch->dai_c = 1; if (pucch->sr_flag + pucch->dai_c == max_acknacks) { /* advance the UL slot information in PUCCH by one so we won't schedule in * the same slot again */ const int f = pucch->frame; const int s = pucch->ul_slot; + if(NFAPI_MODE == NFAPI_MODE_VNF){ + gNB_MAC_INST *gNB = RC.nrmac[mod_id]; + gNB->UL_tti_req_ahead[0][7].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 + gNB->UL_tti_req_ahead[0][8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 + gNB->UL_tti_req_ahead[0][9].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 + gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; + } nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id); memset(pucch, 0, sizeof(*pucch)); pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; @@ -481,6 +491,7 @@ bool nr_acknack_scheduling(int mod_id, UE_id); nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f; + printf("pucch frame filled. \n"); pucch->ul_slot = (s + 2) % n_slots_frame; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 574bdd95b4..4a47e4d894 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -32,6 +32,7 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "executables/softmodem-common.h" #include "common/utils/nr/nr_common.h" +#include "nfapi/oai_integration/vendor_ext.h" //38.321 Table 6.1.3.1-1 const uint32_t NR_SHORT_BSR_TABLE[32] = { @@ -882,6 +883,8 @@ void nr_schedule_ulsch(module_id_t module_id, if (harq_id < 0) { /* PP has not selected a specific HARQ Process, get a new one */ harq_id = sched_ctrl->available_ul_harq.head; + // if(NFAPI_MODE == NFAPI_MODE_VNF) + // harq_id = 1; AssertFatal(harq_id >= 0, "no free HARQ process available for UE %d\n", UE_id); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index b183b32aab..d5f6bb2308 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -105,7 +105,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) } UL_info->uci_ind.num_ucis = 0; - + if(NFAPI_MODE != NFAPI_MODE_PNF) // mark corresponding PUCCH resources as free // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; @@ -181,6 +181,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { NR_Sched_Rsp_t *sched_info = &Sched_INFO[module_id][CC_id]; NR_IF_Module_t *ifi = if_inst[module_id]; gNB_MAC_INST *mac = RC.nrmac[module_id]; + nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rach_pdus:%d rx_ind:%d crcs:%d]\n", UL_info->frame,UL_info->slot, module_id,CC_id, UL_info->rach_ind.number_of_pdus, @@ -199,8 +200,9 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } handle_nr_rach(UL_info); - + handle_nr_uci(UL_info); + // clear HI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; handle_nr_ulsch(UL_info); @@ -212,12 +214,12 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { (UL_info->frame+((UL_info->slot>(9-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%10); */ - nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; + int spf = get_spf(cfg); gNB_dlsch_ulsch_scheduler(module_id, (UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%spf); - + ifi->CC_mask = 0; sched_info->module_id = module_id; sched_info->CC_id = CC_id; From 8d07eacd9eae5b34c194f21589e322734f197acb Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 5 Mar 2021 11:44:31 +0100 Subject: [PATCH 005/185] Added averaging channel est to PUSCH Included command line option to select interpolation method --- executables/softmodem-common.h | 4 + .../NR_ESTIMATION/nr_ul_channel_estimation.c | 104 ++++++++++++++- .../nr_dl_channel_estimation.c | 124 +++++++++--------- 3 files changed, 168 insertions(+), 64 deletions(-) diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index a6035122c0..7b43b51f23 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -72,6 +72,7 @@ extern "C" #define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" #define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" #define CONFIG_HLP_256QAM "Use the 256 QAM mcs table for PDSCH\n" +#define CONFIG_HLP_FDINTER "Do frequency domain linear interpolation for channel estimates. By default, average of estimates over 1 PRB is used." //#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" @@ -112,6 +113,7 @@ extern "C" #define SEND_DMRSSYNC softmodem_params.send_dmrs_sync #define USIM_TEST softmodem_params.usim_test #define USE_256QAM_TABLE softmodem_params.use_256qam_table +#define FD_INTERPOLATION softmodem_params.fd_interpolation #define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat"; @@ -142,6 +144,7 @@ extern "C" {"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \ {"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \ + {"do-fd-interpolation", CONFIG_HLP_FDINTER, PARAMFLAG_BOOL, iptr:&FD_INTERPOLATION, defintval:0, TYPE_INT, 0}, \ } @@ -229,6 +232,7 @@ typedef struct { int hw_timing_advance; uint32_t send_dmrs_sync; int use_256qam_table; + int fd_interpolation; } softmodem_params_t; extern uint64_t get_softmodem_optmask(void); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 713e71674b..34b866fffb 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -31,6 +31,7 @@ #include "PHY/NR_UE_ESTIMATION/filt16a_32.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" +#include "executables/softmodem-common.h" //#define DEBUG_CH @@ -173,7 +174,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #endif //if ((gNB->frame_parms.N_RB_UL&1)==0) { - if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1){ + if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && get_softmodem_params()->fd_interpolation){ // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -381,7 +382,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } #endif } - else { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && get_softmodem_params()->fd_interpolation) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| // Treat first DMRS specially (left edge) @@ -467,6 +468,105 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch_128[0] = _mm_slli_epi16 (ul_ch_128[0], 2); } + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + + for (pilot_cnt=0; pilot_cnt<6*nb_rb_pusch; pilot_cnt+=6) { + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0]/=6; + ch[1]/=6; + ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); + ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; + ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; + ul_ch+=24; + } + } + else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + for (pilot_cnt=0; pilot_cnt<4*nb_rb_pusch; pilot_cnt+=4) { + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + + + pil+=2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0]>>=2; + ch[1]>>=2; + ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); + ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; + ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; + ul_ch+=24; + } + } +#ifdef DEBUG_PDSCH + ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; + for(uint16_t idxP=0; idxP>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0]/=6; - ch[1]/=6; - ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; - ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; - dl_ch+=24; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0]/=6; + ch[1]/=6; + ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); + ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; + ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; + dl_ch+=24; } } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB for (pilot_cnt=0; pilot_cnt<4*nb_rb_pdsch; pilot_cnt+=4) { - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0]>>=2; - ch[1]>>=2; - ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; - ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; - dl_ch+=24; + pil+=2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + ch[0]>>=2; + ch[1]>>=2; + ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); + ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; + ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; + dl_ch+=24; } } #ifdef DEBUG_PDSCH From 0fb6934fed7f71f46655caa8dbc7578568ac7c91 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 5 Mar 2021 12:11:46 +0100 Subject: [PATCH 006/185] Cmd line parameter for UE --- executables/nr-uesoftmodem.c | 4 ++-- executables/nr-uesoftmodem.h | 1 + executables/softmodem-common.h | 2 +- openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 4 ++-- openair1/PHY/defs_nr_UE.h | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 87cd157948..f729e39f8e 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -291,8 +291,8 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->rf_map.chain = CC_id + chain_offset; - LOG_I(PHY,"Set UE mode %d, UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n", - UE->mode, UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction); + LOG_I(PHY,"Set UE mode %d, UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, fd_lin_interpolation %d", + UE->mode, UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->fd_lin_interpolation); // Set FP variables diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 5902c8cca8..3345aafd26 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -60,6 +60,7 @@ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ + {"do-fd-interpolation", CONFIG_HLP_FDINTER, PARAMFLAG_BOOL, iptr:&(UE->fd_lin_interpolation), defintval:0, TYPE_INT, 0}, \ } diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 7b43b51f23..ea99999506 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -72,7 +72,7 @@ extern "C" #define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" #define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" #define CONFIG_HLP_256QAM "Use the 256 QAM mcs table for PDSCH\n" -#define CONFIG_HLP_FDINTER "Do frequency domain linear interpolation for channel estimates. By default, average of estimates over 1 PRB is used." +#define CONFIG_HLP_FDINTER "Do frequency domain linear interpolation for channel estimates. By default, average of estimates over 1 PRB is used\n" //#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 34b866fffb..aabddff885 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -174,7 +174,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #endif //if ((gNB->frame_parms.N_RB_UL&1)==0) { - if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && get_softmodem_params()->fd_interpolation){ + if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && get_softmodem_params()->fd_interpolation == 1){ // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -382,7 +382,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } #endif } - else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && get_softmodem_params()->fd_interpolation) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && get_softmodem_params()->fd_interpolation == 1) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| // Treat first DMRS specially (left edge) diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index bcc24610ff..cb5e11ced8 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -854,7 +854,7 @@ typedef struct { uint32_t perfect_ce; // flag to activate linear interpolation in frequency-domain channel estimation // when off (default), this just averages channel on per-PRB basis - uint32_t fd_lin_interpolation; + int fd_lin_interpolation; int16_t ch_est_alpha; int generate_ul_signal[NUMBER_OF_CONNECTED_gNB_MAX]; From b7dddf084920ae5fd80d0b60181ee2ff7838be20 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 5 Mar 2021 13:54:21 +0100 Subject: [PATCH 007/185] Adding ulsch encoding stats --- openair1/PHY/defs_nr_UE.h | 1 + 1 file changed, 1 insertion(+) diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index cb5e11ced8..cf4f5860f6 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -1013,6 +1013,7 @@ typedef struct { time_stats_t ofdm_mod_stats; time_stats_t ulsch_encoding_stats; + time_stats_t ulsch_ldpc_encoding_stats; time_stats_t ulsch_modulation_stats; time_stats_t ulsch_segmentation_stats; time_stats_t ulsch_rate_matching_stats; From 86c39286524f42c20a49f2dc7805ac46b81268cb Mon Sep 17 00:00:00 2001 From: Shruthi Date: Fri, 5 Mar 2021 21:09:39 +0530 Subject: [PATCH 008/185] Minor build error fix, README improved --- executables/nr-gnb.c | 4 +--- nfapi/nrNFAPI.md | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 5a53c69063..6632289102 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -428,7 +428,7 @@ static void *gNB_L1_thread( void *param ) { if (gNB->CC_id==0) { int next_slot; next_slot = (slot_rx + 1) % 20; - if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break + if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break; } if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); @@ -445,8 +445,6 @@ static void *gNB_L1_thread( void *param ) { if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break; } - clock_gettime(CLOCK_MONOTONIC,&t); - //printf("\n %d.%d",t.tv_sec,t.tv_nsec); if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break; diff --git a/nfapi/nrNFAPI.md b/nfapi/nrNFAPI.md index 299a43fd93..b78a205e84 100644 --- a/nfapi/nrNFAPI.md +++ b/nfapi/nrNFAPI.md @@ -1,17 +1,24 @@ # Procedure to run nFAPI in 5G NR -## Conributed by 5G Testbed IISC -### Developers: Sudhakar B,Mahesh K,Gokul S,Aniq U.R +## Conributed by 5G Testbed IISc + +### Developers: Mahesh K,Gokul S,Aniq U R, Sai Shruthi N, Sudhakar B ## Procedure to Build gNB and UE The regular commands to build gNB and UE can be used ``` -sudo ./build_oai --gNB --UE +sudo ./build_oai --gNB --nrUE ``` ## Procedure to run NR nFAPI using RF-Simulator +### Bring up another loopback interface + +If running for the first time on your computer, or you have restarted your computer, bring up another loopback interface with this command: + +sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up + ### VNF command ``` sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test @@ -28,8 +35,10 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path ``` ## Procedure to run NR nFAPI using Hardware -Will be updated as we have not yet currently tested on hardware + +To be updated. ## Notes -* In order to acheive the synchronization between VNF and PNF and receive the P7 messages within the timing window the order in which we should run the modules on different terminals is UE->VNF->PNF -* Currently only downlink is functional and working as we are still working on uplink functionality +* If running for the first time on local branch, run in the following order - VNF then PNF. This is so that necessary files are generated for the UE to run. Stop this run (it's ok if it stops on its own due to an error). From every subsequent run follow the next bullet. +* In order to achieve synchronization between the VNF and PNF, and receive P7 messages within the timing window, the order in which we should run the modules on different terminals is UE->VNF->PNF. +* Currently downlink transmission from gNB to UE is partially functional and we are working on improving this. Uplink P7 messages are disabled and we will work on uplink integration after completing downlink. From 3fe2628df024997331cbb7f42321ae2b87f6737c Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 5 Mar 2021 16:51:09 +0100 Subject: [PATCH 009/185] fixing build errors --- cmake_targets/phy_simulators/CMakeLists.txt | 2 +- executables/nr-gnb.c | 2 ++ openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 4 ++-- openair1/PHY/defs_gNB.h | 2 ++ openair1/SIMULATION/NR_PHY/ulschsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 1 - 6 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cmake_targets/phy_simulators/CMakeLists.txt b/cmake_targets/phy_simulators/CMakeLists.txt index 447e90bcab..cc2e02b0e3 100644 --- a/cmake_targets/phy_simulators/CMakeLists.txt +++ b/cmake_targets/phy_simulators/CMakeLists.txt @@ -16,5 +16,5 @@ set ( UE_DEBUG_TRACE False ) set ( UE_TIMING_TRACE False ) set ( USRP_REC_PLAY False ) set ( SKIP_SHARED_LIB_FLAG False ) -set ( PHYSIM True) +set ( ITTI_SIM False ) include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 71996cfd29..43d3ea8c5a 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -85,6 +85,7 @@ #include "T.h" #include "nfapi/oai_integration/vendor_ext.h" +#include "executables/softmodem-common.h" //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 @@ -1070,6 +1071,7 @@ void init_gNB(int single_thread_flag,int wait_for_sync) { gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/ gNB->prach_energy_counter = 0; + gNB->fd_interpolation = get_softmodem_params()->fd_interpolation; } diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 43239dd7fd..74cb055466 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -176,7 +176,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #endif //if ((gNB->frame_parms.N_RB_UL&1)==0) { - if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && get_softmodem_params()->fd_interpolation == 1){ + if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && gNB->fd_interpolation == 1){ // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -384,7 +384,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } #endif } - else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && get_softmodem_params()->fd_interpolation == 1) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && gNB->fd_interpolation == 1) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| // Treat first DMRS specially (left edge) diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index b7923adb0b..2ccdd9ca69 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -785,6 +785,8 @@ typedef struct PHY_VARS_gNB_s { int **dl_precoder_SgNB[3]; char log2_maxp; /// holds the maximum channel/precoder coefficient + int fd_interpolation; + /// if ==0 enables phy only test mode int mac_enabled; /// counter to average prach energh over first 100 prach opportunities diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 7deb0b66d1..3686be8805 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -504,7 +504,7 @@ int main(int argc, char **argv) unsigned int G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, Nl); if (input_fd == NULL) { - nr_ulsch_encoding(ue, ulsch_ue, frame_parms, harq_pid, G); + nr_ulsch_encoding(UE, ulsch_ue, frame_parms, harq_pid, G); } printf("\n"); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index ea66f78776..57b8a51d58 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -921,7 +921,6 @@ int main(int argc, char **argv) crc_status = 1; errors_decoding = 0; memset((void*)roundStats,0,50*sizeof(roundStats[0])); - ulsch_ue[0]->harq_processes[harq_pid]->ndi = 1; while (roundharq_processes[harq_pid]->round = round; From 9a623a2b451e87db3ba47a663f3d6e23e0586c18 Mon Sep 17 00:00:00 2001 From: Shruthi Date: Fri, 5 Mar 2021 21:45:38 +0530 Subject: [PATCH 010/185] pdcch pdu pack/unpack fix --- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 8b1060f691..9f90d8852c 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -267,7 +267,7 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { - if(!push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && + if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && @@ -277,7 +277,7 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)) + pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) return 0; } @@ -3757,7 +3757,7 @@ static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { - if(!pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && + if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && @@ -3768,7 +3768,7 @@ static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)) + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) return 0; } From 6e61393f7e22dd421ca6dd89434088ee93889135 Mon Sep 17 00:00:00 2001 From: Shruthi Date: Sat, 6 Mar 2021 15:18:02 +0530 Subject: [PATCH 011/185] DCI payload corrections in nFAPI mode --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 92cb65aa57..fb704dc964 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -57,6 +57,9 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) +int harq_rounds = 0; +int harq_pid = 0; + // Compute and write all MAC CEs and subheaders, and return number of written // bytes int nr_write_ce_dlsch_pdu(module_id_t module_idP, @@ -821,6 +824,14 @@ void nr_schedule_ue_spec(module_id_t module_id, pdsch_pdu->mcsIndex[0] = sched_ctrl->mcs; pdsch_pdu->mcsTable[0] = sched_ctrl->mcsTableIdx; pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round]; + if (NFAPI_MODE == NFAPI_MODE_VNF){ // done since uplink isnt operational yet which means harq structures dont get filled properly + pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq_rounds]; + if (harq_rounds % 5 == 0 && harq_rounds!=0){ + harq_rounds = 0; + harq_pid = (harq_pid + 1) % 16; + } + harq_rounds++; + } pdsch_pdu->TBSize[0] = TBS; pdsch_pdu->dataScramblingId = *scc->physCellId; @@ -932,6 +943,10 @@ void nr_schedule_ue_spec(module_id_t module_id, const int dci_format = f ? NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0; const int rnti_type = NR_RNTI_C; + if (NFAPI_MODE == NFAPI_MODE_VNF){ + dci_payload.harq_pid = harq_pid; + dci_payload.tpc = 2; + } fill_dci_pdu_rel15(scc, UE_info->secondaryCellGroup[UE_id], dci_pdu, From 43042395201a46daf95090dccd0e591d2c678e2d Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 8 Mar 2021 16:26:35 +0100 Subject: [PATCH 012/185] fixing build issue --- cmake_targets/phy_simulators/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/phy_simulators/CMakeLists.txt b/cmake_targets/phy_simulators/CMakeLists.txt index cc2e02b0e3..447e90bcab 100644 --- a/cmake_targets/phy_simulators/CMakeLists.txt +++ b/cmake_targets/phy_simulators/CMakeLists.txt @@ -16,5 +16,5 @@ set ( UE_DEBUG_TRACE False ) set ( UE_TIMING_TRACE False ) set ( USRP_REC_PLAY False ) set ( SKIP_SHARED_LIB_FLAG False ) -set ( ITTI_SIM False ) +set ( PHYSIM True) include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt) From 6610ce11f1925bdb30d5c6cf6bf9b7260ac0b326 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 9 Mar 2021 16:17:56 +0100 Subject: [PATCH 013/185] Updated phy_simulators to use new chest Added a CI test case for dlsim to test 256 QAM --- cmake_targets/autotests/test_case_list.xml | 42 ++++++++++++---------- openair1/SIMULATION/NR_PHY/dlsim.c | 14 ++++---- openair1/SIMULATION/NR_PHY/ulsim.c | 16 ++++----- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 089d0503fd..e76ed15a48 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1100,7 +1100,9 @@ (Test15: 6 PTRS, 5 Interpolated Symbols), (Test16: 11 PTRS, 0 Interpolated Symbols), (Test17: 2 DMRS Symbols), - (Test18: 3 DMRS Symbols) + (Test18: 3 DMRS Symbols), + (Test19: 106 PDSCH-PRBs MCS 28), + (Test20: 256 QAM MCS 27) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1108,24 +1110,26 @@ $OPENAIR_DIR/targets/bin/nr_dlsim.Rel15 -n100 -R106 -b106 -s5 - -n100 -R217 -b217 -s5 - -n100 -R273 -b273 -s5 - -n100 -R106 -a25 -s5 - -n100 -R106 -a51 -s5 - -n100 -R217 -b100 -s5 - -n100 -R217 -a80 -s5 - -n100 -R217 -a110 -s5 -b100 - -n100 -e27 -s30 - -n100 -e16 -s10 - -n100 -s1 -t25 - -n100 -s1 -t33 - -n100 -s1 -t50 - -n100 -s5 -T 2 2 2 - -n100 -s5 -T 2 1 2 - -n100 -s5 -T 2 0 4 - -n100 -s2 -U 2 0 1 - -n100 -s2 -U 2 0 2 - nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13 nr_dlsim.test14 nr_dlsim.test15 nr_dlsim.test16 nr_dlsim.test17 nr_dlsim.test18 + -n100 -R217 -b217 -s5 + -n100 -R273 -b273 -s5 + -n100 -R106 -a25 -s5 + -n100 -R106 -a51 -s5 + -n100 -R217 -b100 -s5 + -n100 -R217 -a80 -s5 + -n100 -R217 -a110 -s5 -b100 + -n100 -e27 -s30 + -n100 -e16 -s10 + -n100 -s1 -t25 + -n100 -s1 -t33 + -n100 -s1 -t50 + -n100 -s5 -T 2 2 2 + -n100 -s5 -T 2 1 2 + -n100 -s5 -T 2 0 4 + -n100 -s2 -U 2 0 1 + -n100 -s2 -U 2 0 2 + -n100 -s25 -e28 -t75 + -n100 -s35 -q -e27 -t75 + nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13 nr_dlsim.test14 nr_dlsim.test15 nr_dlsim.test16 nr_dlsim.test17 nr_dlsim.test18 nr_dlsim.test19 nr_dlsim.test20 PDSCH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 9925b6911a..98c3216b7c 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -323,6 +323,7 @@ int main(int argc, char **argv) uint16_t rbSize = 106; uint8_t mcsIndex = 9; uint8_t dlsch_threads = 0; + int fd_inter = 0; if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) { exit_fun("[NR_DLSIM] Error, configuration module init failed\n"); } @@ -333,7 +334,7 @@ int main(int argc, char **argv) FILE *scg_fd=NULL; - while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:d:e:m:w:T:U:q")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:d:e:m:w:T:U:qi")) != -1) { switch (c) { case 'f': scg_fd = fopen(optarg,"r"); @@ -385,14 +386,10 @@ int main(int argc, char **argv) break; - /*case 'i': - interf1=atoi(optarg); + case 'i': + fd_inter=1; break; - case 'j': - interf2=atoi(optarg); - break;*/ - case 'n': n_trials = atoi(optarg); break; @@ -552,7 +549,7 @@ int main(int argc, char **argv) printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n"); printf("-y Number of TX antennas used in gNB\n"); printf("-z Number of RX antennas used in UE\n"); - //printf("-i Relative strength of first intefering gNB (in dB) - cell_id mod 3 = 1\n"); + printf("-i Activate freq domain interpolation for channel estimation. Average over 1 PRB by default.\n"); //printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n"); printf("-R N_RB_DL\n"); printf("-O oversampling factor (1,2,4,8,16)\n"); @@ -817,6 +814,7 @@ int main(int argc, char **argv) UE->if_inst->phy_config_request = nr_ue_phy_config_request; UE->if_inst->dl_indication = nr_ue_dl_indication; UE->if_inst->ul_indication = dummy_nr_ue_ul_indication; + UE->fd_lin_interpolation = fd_inter; UE_mac->if_module = nr_ue_if_module_init(0); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 57b8a51d58..47c0078c94 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -235,6 +235,7 @@ int main(int argc, char **argv) float effRate; //float eff_tp_check = 0.7; uint8_t snrRun; + int fd_inter = 0; int enable_ptrs = 0; int modify_dmrs = 0; @@ -270,7 +271,7 @@ int main(int argc, char **argv) /* initialize the sin-cos table */ InitSinLUT(); - while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:i:j:kl:m:n:p:r:s:y:z:F:G:H:M:N:PR:S:T:U:L:Z")) != -1) { + while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:j:kl:m:n:p:r:s:y:z:F:G:H:M:N:PR:S:T:U:L:Zi")) != -1) { printf("handling optarg %c\n",c); switch (c) { @@ -362,14 +363,10 @@ int main(int argc, char **argv) break; - /*case 'i': - interf1 = atoi(optarg); - break; + case 'i': + fd_inter=1; + break; - case 'j': - interf2 = atoi(optarg); - break;*/ - case 'k': printf("Setting threequarter_fs_flag\n"); openair0_cfg[0].threequarter_fs= 1; @@ -521,7 +518,7 @@ int main(int argc, char **argv) printf("-f Number of frames to simulate\n"); printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n"); printf("-h This message\n"); - //printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n"); + printf("-i Activate freq domain interpolation for channel estimation. Average over 1 PRB by default.\n"); //printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n"); printf("-s Starting SNR, runs from SNR0 to SNR0 + 10 dB if ending SNR isn't given\n"); printf("-m MCS value\n"); @@ -604,6 +601,7 @@ int main(int argc, char **argv) gNB->UL_INFO.crc_ind.crc_list = (nfapi_nr_crc_t *)malloc(NB_UE_INST*sizeof(nfapi_nr_crc_t)); gNB->UL_INFO.rx_ind.number_of_pdus = 0; gNB->UL_INFO.crc_ind.number_crcs = 0; + gNB->fd_interpolation = fd_inter; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) From 39577ba0d802fe3de26ee55d8807c6c92c6c403e Mon Sep 17 00:00:00 2001 From: Mahesh Date: Thu, 11 Mar 2021 12:49:40 +0530 Subject: [PATCH 014/185] UL P7 messages and UL scheduling re-enabled. Disabled HARQ from the UE side --> DL CRC OK --- nfapi/open-nFAPI/nfapi/src/nfapi.c | 2 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 16 +++---- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 2 +- openair1/SCHED_NR/fapi_nr_l1.c | 16 +++---- openair1/SCHED_NR_UE/harq_nr.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 6 +-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 3 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 44 +++++++++++-------- 8 files changed, 49 insertions(+), 42 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index ba800c3634..6ca64138f2 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -189,7 +189,7 @@ uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end) return 1; } else - { + { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); return 0; } diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 9f90d8852c..49ecba5eac 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -2047,7 +2047,7 @@ static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { - if(!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && + if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && @@ -2058,7 +2058,7 @@ static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) return 0; } @@ -2078,7 +2078,9 @@ static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end)); + push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); } @@ -5834,10 +5836,9 @@ static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPack static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) { nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) { - if(!pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && + if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && @@ -5848,7 +5849,7 @@ static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t * pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end)); + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) return 0; } @@ -5869,7 +5870,6 @@ static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t * pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); @@ -8052,7 +8052,7 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; uint8_t *pReadPackedMessage = pMessageBuf; uint8_t *end = pMessageBuf + messageBufLen; - + if (pMessageBuf == NULL || pUnpackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index fa919ac3a5..fefd822bb0 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -2009,7 +2009,7 @@ void pnf_handle_ul_dci_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack hi_dci0_req\n"); + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack UL DCI req\n"); deallocate_nfapi_ul_dci_request(req, pnf_p7); } } diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 15c2a5c988..2aa09dea80 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -234,15 +234,15 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ } } - // if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) - // { - // oai_nfapi_ul_tti_req(UL_tti_req); - // } + if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) + { + oai_nfapi_ul_tti_req(UL_tti_req); + } - // if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) - // { - // oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); - // } + if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) + { + oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); + } if (NFAPI_MODE != NFAPI_MONOLITHIC) { diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 85f6d90bbe..0dcc057867 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -472,7 +472,7 @@ harq_result_t downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int dl_harq->round = 0; dl_harq->status = ACTIVE; dl_harq->DCINdi = ndi; - dl_harq->first_tx = 0; + //dl_harq->first_tx = 0; result_harq = NEW_TRANSMISSION_HARQ; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index e2d5db0799..4ada9eb9f3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -394,10 +394,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // clear last scheduled slot's content (only)! const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; const int last_slot = (slot + num_slots - 1) % num_slots; - const int two_slots_back = (slot + num_slots - 2) % num_slots; uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); - memset(&vrb_map_UL[two_slots_back * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); } @@ -448,13 +446,13 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, gNB->UL_tti_req_ahead[0][9].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; } - //nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); + nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); } // This schedules the DCI for Downlink and PDSCH if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot)) nr_schedule_ue_spec(module_idP, frame, slot); - //nr_schedule_pucch(module_idP, frame, slot); + nr_schedule_pucch(module_idP, frame, slot); stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 9e3a611356..9842d9137f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -460,7 +460,8 @@ bool nr_acknack_scheduling(int mod_id, "illegal number of bits in PUCCH of UE %d\n", UE_id); /* if the currently allocated PUCCH of this UE is full, allocate it */ - pucch->sr_flag = 1; pucch->dai_c = 1; + if (NFAPI_MODE == NFAPI_MODE_VNF) + pucch->sr_flag = 1; pucch->dai_c = 1; if (pucch->sr_flag + pucch->dai_c == max_acknacks) { /* advance the UL slot information in PUCCH by one so we won't schedule in * the same slot again */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index db7dde0140..94aa4f5159 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -883,30 +883,38 @@ void nr_schedule_ulsch(module_id_t module_id, uint16_t rnti = UE_info->rnti[UE_id]; int8_t harq_id = sched_pusch->ul_harq_pid; - if (harq_id < 0) { - /* PP has not selected a specific HARQ Process, get a new one */ - harq_id = sched_ctrl->available_ul_harq.head; - // if(NFAPI_MODE == NFAPI_MODE_VNF) - // harq_id = 1; - AssertFatal(harq_id >= 0, - "no free HARQ process available for UE %d\n", - UE_id); - remove_front_nr_list(&sched_ctrl->available_ul_harq); - sched_pusch->ul_harq_pid = harq_id; - } else { - /* PP selected a specific HARQ process. Check whether it will be a new - * transmission or a retransmission, and remove from the corresponding - * list */ - if (sched_ctrl->ul_harq_processes[harq_id].round == 0) - remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); - else - remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id); + if (NFAPI_MODE == NFAPI_MODE_VNF) + harq_id = 1; + else + { + if (harq_id < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + harq_id = sched_ctrl->available_ul_harq.head; + // if(NFAPI_MODE == NFAPI_MODE_VNF) + // harq_id = 1; + AssertFatal(harq_id >= 0, + "no free HARQ process available for UE %d\n", + UE_id); + remove_front_nr_list(&sched_ctrl->available_ul_harq); + sched_pusch->ul_harq_pid = harq_id; + } else { + /* PP selected a specific HARQ process. Check whether it will be a new + * transmission or a retransmission, and remove from the corresponding + * list */ + if (sched_ctrl->ul_harq_processes[harq_id].round == 0) + remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); + else + remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id); + } } NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id]; DevAssert(!cur_harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); cur_harq->feedback_slot = sched_pusch->slot; cur_harq->is_waiting = true; + if (NFAPI_MODE == NFAPI_MODE_VNF) + cur_harq->is_waiting = 0; + int rnti_types[2] = { NR_RNTI_C, 0 }; From b232c4347760b127ffa0737c6d0cde292cda9de1 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 16 Mar 2021 12:49:46 +0530 Subject: [PATCH 015/185] Uplink improvement --- executables/nr-gnb.c | 36 +++-- executables/nr-ru.c | 8 +- nfapi/oai_integration/nfapi_pnf.c | 1 + nfapi/open-nFAPI/pnf/src/pnf_p7.c | 53 ++++--- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 8 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 17 ++- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 7 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 141 +++++++++--------- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 23 +-- 9 files changed, 172 insertions(+), 122 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 6632289102..5e63c54ab8 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -253,25 +253,33 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t // RX processing int tx_slot_type; int rx_slot_type; - if(NFAPI_MODE == NFAPI_MODE_VNF) { - if ((slot_tx==8) || (slot_rx==8) || (slot_tx==9) || (slot_rx==9) || (slot_tx==18) || (slot_rx==18) || (slot_tx==19) || (slot_rx==19)) { - tx_slot_type = NR_UPLINK_SLOT; - rx_slot_type = NR_UPLINK_SLOT; - } - else if ((slot_tx==7) || (slot_rx==7) || (slot_tx==17) || (slot_rx==17)) { - tx_slot_type = NR_MIXED_SLOT; - rx_slot_type = NR_MIXED_SLOT; - } - else { - tx_slot_type = NR_DOWNLINK_SLOT; - rx_slot_type = NR_DOWNLINK_SLOT; - } + if(NFAPI_MODE != NFAPI_MONOLITHIC) { //slot selection routines not working properly in nfapi, so temporarily hardcoding + if ((slot_tx==8) || (slot_tx==9) || (slot_tx==18) || (slot_tx==19)) { //tx slot config + tx_slot_type = NR_UPLINK_SLOT; + } + else if ((slot_tx==7) || (slot_tx==17)) { + tx_slot_type = NR_MIXED_SLOT; + } + else { + tx_slot_type = NR_DOWNLINK_SLOT;; + } + + if ((slot_rx==8) || (slot_rx==9) || (slot_rx==18) || (slot_rx==19)) { // rx slot config + rx_slot_type = NR_UPLINK_SLOT; + } + else if ((slot_rx==7) || (slot_rx==17)) { + rx_slot_type = NR_MIXED_SLOT; + } + else { + rx_slot_type = NR_DOWNLINK_SLOT;; + } + + } else { tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); } - if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { // UE-specific RX processing for subframe n // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 1184a9d80c..d0bc1a3e0e 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1607,7 +1607,13 @@ void *ru_thread( void *param ) { // do RX front-end processing (frequency-shift, dft) if needed - int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + //int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + //if (NFAPI_MODE == NFAPI_MODE_PNF) + int slot_type; + if (slot ==7) + slot_type = NR_MIXED_SLOT; + if (slot == 8) + slot_type = NR_UPLINK_SLOT; if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { //if (proc->tti_rx==8) { diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 20db37b123..e744fcbb24 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1475,6 +1475,7 @@ int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, switch (ul_tti_pdu_list[i].pdu_type) { case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + //curr_sfn = curr_sfn + 3; //Gokul nr_fill_ulsch(gNB,curr_sfn, curr_slot, &ul_tti_pdu_list[i].pusch_pdu); break; case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index fefd822bb0..14b4846846 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1007,36 +1007,34 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl // if(tx_slot_buffer->slot == slot_tx && tx_slot_buffer->sfn == sfn_tx) // { - if(tx_slot_buffer->tx_data_req != 0) - { + if(tx_slot_buffer->tx_data_req != 0) + { - if(pnf_p7->_public.tx_data_req_fn) - { - (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); - } + if(pnf_p7->_public.tx_data_req_fn) + { + (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); } - else + } + else + { + // send dummy + if(pnf_p7->_public.tx_data_req_fn && pnf_p7->_public.dummy_slot.tx_data_req) { - // send dummy - if(pnf_p7->_public.tx_data_req_fn && pnf_p7->_public.dummy_slot.tx_data_req) - { - pnf_p7->_public.dummy_slot.tx_data_req->SFN = sfn_tx; - pnf_p7->_public.dummy_slot.tx_data_req->Slot = slot_tx; + pnf_p7->_public.dummy_slot.tx_data_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.tx_data_req->Slot = slot_tx; - (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), pnf_p7->_public.dummy_slot.tx_data_req); - } + (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), pnf_p7->_public.dummy_slot.tx_data_req); } - //} + } + - if( tx_slot_buffer->dl_tti_req != 0) // ADDED & TO BYPASS ERROR + if(tx_slot_buffer->dl_tti_req != 0) { if(pnf_p7->_public.dl_tti_req_fn) { (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->dl_tti_req); } } - - else { // send dummy @@ -1048,6 +1046,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl } } + if(tx_slot_buffer->ul_dci_req!= 0) { if(pnf_p7->_public.ul_dci_req_fn) @@ -1065,6 +1064,23 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_dci_req); } } + if(tx_slot_buffer->ul_tti_req != 0) + { + if(pnf_p7->_public.ul_tti_req_fn) + { + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_tti_req); + } + } + else + { + // send dummy + if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) + { + pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot_tx; + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); + } + } if(tx_slot_buffer->dl_tti_req != 0) { deallocate_nfapi_dl_tti_request(tx_slot_buffer->dl_tti_req, pnf_p7); @@ -1101,7 +1117,6 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl { (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), slot_buffer->ul_tti_req); } - //deallocate_nfapi_ul_config_request(subframe_buffer->ul_config_req, pnf_p7); } else { diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index d990176d79..0b0851dddb 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -430,14 +430,14 @@ void nr_processULSegment(void* arg) { p_procTime); if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) { -#ifdef PRINT_CRC_CHECK +// #ifdef PRINT_CRC_CHECK LOG_I(PHY, "Segment %d CRC OK\n",r); -#endif +// #endif rdata->decodeIterations = no_iteration_ldpc; } else { -#ifdef PRINT_CRC_CHECK +// #ifdef PRINT_CRC_CHECK LOG_I(PHY, "CRC NOK\n"); -#endif +// #endif rdata->decodeIterations = max_ldpc_iterations + 1; } diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 2d1fdff4be..3d2f27476a 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -47,6 +47,7 @@ #include "PHY/NR_REFSIG/nr_refsig.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "nfapi/oai_integration/vendor_ext.h" #include "T.h" @@ -86,7 +87,8 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - + if (NFAPI_MODE == NFAPI_MODE_PNF) + gNB->pucch[0]->active = 0; //check if ture in monolithic mode int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idrnti,id); @@ -164,10 +166,15 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu) { - + printf("Inside nr_decode_pucch0. \n"); int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - + //Gokul + // printf("rxdataf buff: \n"); + // for(int i = 1;i<=5*7*14*512;++i){ + // if(gNB->RU_list[0]->common.rxdataF[0][i] != 0) + // printf("%d ",gNB->RU_list[0]->common.rxdataF[0][i]); + // } int nr_sequences; const uint8_t *mcs; @@ -1085,7 +1092,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu) { - + printf("Inside nr_decode_pucch2. \n"); int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); @@ -1465,7 +1472,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } } // cw loop corr_dB = dB_fixed64((uint64_t)corr); - LOG_D(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); + LOG_I(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); decodedPayload[0]=(uint64_t)cw_ML; } else { // polar coded case diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 9f97b7eadf..7e7aff0a09 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -560,6 +560,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) for (int i=0;ipucch[i]; if (pucch) { + if (NFAPI_MODE == NFAPI_MODE_PNF) + pucch->frame = frame_rx; if ((pucch->active == 1) && (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { @@ -620,12 +622,15 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) for (harq_pid=0;harq_pidharq_processes[harq_pid]; AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); + //printf("ulsch_harq->frame = %d, frame_rx = %d \n", ulsch_harq->frame, frame_rx); + if (NFAPI_MODE == NFAPI_MODE_PNF) + ulsch_harq->frame = frame_rx; if ((ulsch_harq->status == NR_ACTIVE) && (ulsch_harq->frame == frame_rx) && (ulsch_harq->slot == slot_rx) && (ulsch_harq->handled == 0)){ - LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n", + LOG_I(PHY, "PUSCH detection started in frame %d slot %d\n", frame_rx,slot_rx); #ifdef DEBUG_RXDATA diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 9842d9137f..3ae3707962 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -318,13 +318,15 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) -{ +{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + UE_info->active[0] = 1; + UE_info->rnti[0] = uci_01->rnti; int UE_id = find_nr_UE_id(mod_id, uci_01->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); return; } - NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; // tpc (power control) @@ -332,51 +334,55 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, uci_01->ul_cqi, 30); - NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; - const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - if (((uci_01->pduBitmap >> 1) & 0x01)) { - // iterate over received harq bits - for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { - const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; - const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; - const int feedback_slot = (slot - 1 + num_slots) % num_slots; - /* In case of realtime problems: we can only identify a HARQ process by - * timing. If the HARQ process's feedback_slot is not the one we - * expected, we assume that processing has been aborted and we need to - * skip this HARQ process, which is what happens in the loop below. If - * you don't experience real-time problems, you might simply revert the - * commit that introduced these changes. */ - int8_t pid = sched_ctrl->feedback_dl_harq.head; - DevAssert(pid >= 0); - while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { - LOG_W(MAC, - "expected feedback slot %d, but found %d instead\n", - sched_ctrl->harq_processes[pid].feedback_slot, - feedback_slot); - remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - handle_dl_harq(mod_id, UE_id, pid, 0); - pid = sched_ctrl->feedback_dl_harq.head; - DevAssert(pid >= 0); - } - remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; - DevAssert(harq->is_waiting); - handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); - } - } + // NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + // const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int num_slots = 20; + + // if (((uci_01->pduBitmap >> 1) & 0x01)) { + // // iterate over received harq bits + // for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { + // const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; + // const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; + // const int feedback_slot = (slot - 1 + num_slots) % num_slots; + // /* In case of realtime problems: we can only identify a HARQ process by + // * timing. If the HARQ process's feedback_slot is not the one we + // * expected, we assume that processing has been aborted and we need to + // * skip this HARQ process, which is what happens in the loop below. If + // * you don't experience real-time problems, you might simply revert the + // * commit that introduced these changes. */ + // int8_t pid = sched_ctrl->feedback_dl_harq.head; + // DevAssert(pid >= 0); + // while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { + // LOG_W(MAC, + // "expected feedback slot %d, but found %d instead\n", + // sched_ctrl->harq_processes[pid].feedback_slot, + // feedback_slot); + // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + // handle_dl_harq(mod_id, UE_id, pid, 0); + // pid = sched_ctrl->feedback_dl_harq.head; + // DevAssert(pid >= 0); + // } + // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + // NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; + // DevAssert(harq->is_waiting); + // handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); + // } + // } } void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) -{ +{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + UE_info->active[0] = 1; + UE_info->rnti[0] = uci_234->rnti; int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); return; } - NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; // tpc (power control) @@ -384,37 +390,38 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, uci_234->ul_cqi, 30); - NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; - const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - if ((uci_234->pduBitmap >> 1) & 0x01) { - // iterate over received harq bits - for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { - const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; - const int feedback_slot = (slot - 1 + num_slots) % num_slots; - /* In case of realtime problems: we can only identify a HARQ process by - * timing. If the HARQ process's feedback_slot is not the one we - * expected, we assume that processing has been aborted and we need to - * skip this HARQ process, which is what happens in the loop below. If - * you don't experience real-time problems, you might simply revert the - * commit that introduced these changes. */ - int8_t pid = sched_ctrl->feedback_dl_harq.head; - DevAssert(pid >= 0); - while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { - LOG_W(MAC, - "expected feedback slot %d, but found %d instead\n", - sched_ctrl->harq_processes[pid].feedback_slot, - feedback_slot); - remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - handle_dl_harq(mod_id, UE_id, pid, 0); - pid = sched_ctrl->feedback_dl_harq.head; - DevAssert(pid >= 0); - } - remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; - DevAssert(harq->is_waiting); - handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); - } - } + // NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + // const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int num_slots = 20; + // if ((uci_234->pduBitmap >> 1) & 0x01) { + // // iterate over received harq bits + // for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { + // const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; + // const int feedback_slot = (slot - 1 + num_slots) % num_slots; + // /* In case of realtime problems: we can only identify a HARQ process by + // * timing. If the HARQ process's feedback_slot is not the one we + // * expected, we assume that processing has been aborted and we need to + // * skip this HARQ process, which is what happens in the loop below. If + // * you don't experience real-time problems, you might simply revert the + // * commit that introduced these changes. */ + // int8_t pid = sched_ctrl->feedback_dl_harq.head; + // DevAssert(pid >= 0); + // while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { + // LOG_W(MAC, + // "expected feedback slot %d, but found %d instead\n", + // sched_ctrl->harq_processes[pid].feedback_slot, + // feedback_slot); + // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + // handle_dl_harq(mod_id, UE_id, pid, 0); + // pid = sched_ctrl->feedback_dl_harq.head; + // DevAssert(pid >= 0); + // } + // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + // NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; + // DevAssert(harq->is_waiting); + // handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); + // } + // } } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index d5f6bb2308..9c118ec53b 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -139,17 +139,18 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot, - rx->rnti, - crc->tb_crc_status ? NULL : rx->pdu, - rx->pdu_length, - rx->timing_advance, - rx->ul_cqi, - rx->rssi); - handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); + //Gokul + // nr_rx_sdu(UL_info->module_id, + // UL_info->CC_id, + // UL_info->rx_ind.sfn, + // UL_info->rx_ind.slot, + // rx->rnti, + // crc->tb_crc_status ? NULL : rx->pdu, + // rx->pdu_length, + // rx->timing_advance, + // rx->ul_cqi, + // rx->rssi); + //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) } // for (i=0;irx_ind.number_of_pdus;i++) From 4454627ba364d348269131a050f3bef6ce53707f Mon Sep 17 00:00:00 2001 From: Mahesh Date: Wed, 17 Mar 2021 14:43:05 +0530 Subject: [PATCH 016/185] Uplink constellation + CRC OK --- executables/nr-gnb.c | 6 +++++- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 3 +++ openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 14 +++++++------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 7 +++++++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 5e63c54ab8..2f7944e313 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -428,7 +428,11 @@ static void *gNB_L1_thread( void *param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); int frame_rx = L1_proc->frame_rx; - int slot_rx = L1_proc->slot_rx; + int slot_rx; + if (NFAPI_MODE == NFAPI_MODE_PNF) + slot_rx = (L1_proc->slot_rx) + 1; + else + slot_rx = L1_proc->slot_rx; int frame_tx = L1_proc->frame_tx; int slot_tx = L1_proc->slot_tx; uint64_t timestamp_tx = L1_proc->timestamp_tx; diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 0b0851dddb..91f72922e2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -443,7 +443,9 @@ void nr_processULSegment(void* arg) { for (int m=0; m < Kr>>3; m ++) { ulsch_harq->c[r][m]= (uint8_t) llrProcBuf[m]; + //printf("%x ", ulsch_harq->c[r][m]); } + //printf("\n"); //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); } @@ -510,6 +512,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, A = (harq_process->TBS)<<3; LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, n_layers %d\n",harq_pid,A,G, mcs, n_layers, nb_rb, Qm, n_layers); + //printf("ULSCH in %d.%d \n", frame, nr_tti_rx); if (R<1024) Coderate = (float) R /(float) 1024; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index d9bea8a3ac..f6a346aee9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -275,13 +275,13 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, ///////////////////////// a---->| add CRC |---->b ///////////////////////// /////////// - /* - int i; - printf("ulsch (tx): \n"); - for (i=0;i<(A>>3);i++) - printf("%02x.",a[i]); - printf("\n"); - */ + + // int i; + // printf("ulsch (tx): \n"); + // for (i=0;i<(A>>3);i++) + // printf("%x ",harq_process->a[i]); + // printf("\n"); + if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index e7149c5d65..00e53dd21e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -62,6 +62,7 @@ #include "common/ran_context.h" extern RAN_CONTEXT_t RC; +uint8_t count = 0; uint8_t harq_pid_ul = -1; int flag = 0; // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs /// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config) @@ -1248,6 +1249,11 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, case NR_UL_DCI_FORMAT_0_1: switch (rnti_type) { case NR_RNTI_C: + harq_pid_ul = (harq_pid_ul + 1) % 16; + if (harq_pid_ul == 0) + flag = !flag; + dci_pdu_rel15->ndi = flag; + // Indicating a DL DCI format 1bit pos = 1; *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos); @@ -1280,6 +1286,7 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); // HARQ process number 4bit pos += 4; + dci_pdu_rel15->harq_pid = harq_pid_ul; *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); // 1st Downlink assignment index pos += dci_pdu_rel15->dai[0].nbits; From 88c36546f824894ae97dac77b16da89189995aae Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 23 Mar 2021 11:45:45 +0100 Subject: [PATCH 017/185] command line parameters for SA UE --- executables/nr-softmodem-common.h | 2 +- executables/nr-uesoftmodem.c | 4 --- executables/nr-uesoftmodem.h | 42 ++++++++++++++++--------------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 500819e684..870f1546f6 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -70,9 +70,9 @@ #define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" #define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" #define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" -#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" #define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" +#define CONFIG_HLP_MUSSB "Set the SSB SCS for UE SA\n" #define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" #define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" #define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n" diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 2854457eee..916d01c3e1 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -295,15 +295,11 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ // Set FP variables - - if (tddflag){ fp->frame_type = TDD; LOG_I(PHY, "Set UE frame_type %d\n", fp->frame_type); } - LOG_I(PHY, "Set UE N_RB_DL %d\n", fp->N_RB_DL); - LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs); } diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 5902c8cca8..153f648865 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -40,26 +40,28 @@ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_NRUE_PHYPARAMS_DESC { \ - { CALIBRX_OPT, CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - { CALIBRXMED_OPT, CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - { CALIBRXBYP_OPT, CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ - { DBGPRACH_OPT, CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - { NOL2CONNECT_OPT, CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - {CALIBPRACH_OPT, CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ - { DUMPFRAME_OPT, CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \ - {"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ - {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \ - {"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ - {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&(fp->nb_antennas_rx), defuintval:1, TYPE_UINT8, 0}, \ - {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&(fp->nb_antennas_tx), defuintval:1, TYPE_UINT8, 0}, \ - {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&(UE->UE_scan_carrier), defintval:0, TYPE_INT, 0}, \ - {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&(UE->UE_fo_compensation), defintval:0, TYPE_INT, 0}, \ - {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ - {"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:25, TYPE_UINT, 0}, \ - {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ - {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ - {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ - {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ + { CALIBRX_OPT, CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + { CALIBRXMED_OPT, CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + { CALIBRXBYP_OPT, CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + { DBGPRACH_OPT, CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + { NOL2CONNECT_OPT, CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + {CALIBPRACH_OPT, CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + { DUMPFRAME_OPT, CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \ + {"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:0, TYPE_DOUBLE,0}, \ + {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE,0}, \ + {"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE,0}, \ + {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&(fp->nb_antennas_rx), defuintval:1, TYPE_UINT8, 0}, \ + {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&(fp->nb_antennas_tx), defuintval:1, TYPE_UINT8, 0}, \ + {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&(UE->UE_scan_carrier), defintval:0, TYPE_INT, 0}, \ + {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&(UE->UE_fo_compensation), defintval:0, TYPE_INT, 0}, \ + {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF,TYPE_UINT64,0}, \ + {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ + {"m" , CONFIG_HLP_MUSSB, 0, u8ptr:&(fp->numerology_index), defintval:0, TYPE_UINT8, 0}, \ + {"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:106, TYPE_UINT, 0}, \ + {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ + {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ } From 62b68e788cb665bdb6079a8d32ec67daa3e3d1d4 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 23 Mar 2021 15:47:46 +0100 Subject: [PATCH 018/185] init frame parms ue sa --- common/utils/nr/nr_common.c | 34 +++++++++++++++ common/utils/nr/nr_common.h | 1 + executables/nr-softmodem-common.h | 1 + executables/nr-uesoftmodem.c | 14 +++--- executables/nr-uesoftmodem.h | 3 +- openair1/PHY/INIT/nr_init.c | 36 ---------------- openair1/PHY/INIT/nr_parms.c | 71 +++++++++++++++++++++++-------- openair1/PHY/INIT/phy_init.h | 2 +- 8 files changed, 101 insertions(+), 61 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 0671aed813..43bc22c97c 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -106,6 +106,40 @@ nr_bandentry_t nr_bandtable[] = { {261,27500040,28350000,27500040,28350000, 2,2070833, 120} }; +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) +{ + const uint64_t dl_freq_khz = downlink_frequency / 1000; + const int32_t delta_duplex_khz = delta_duplex / 1000; + + uint64_t center_freq_diff_khz = 999999999999999999; // 2^64 + uint16_t current_band = 0; + + for (int ind = 0; ind < nr_bandtable_size; ind++) { + + if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max) + continue; + + int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min; + + if (current_offset_khz != delta_duplex_khz) + continue; + + uint64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; + + if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ + current_band = nr_bandtable[ind].band; + center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); + } + } + + printf("DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n", + downlink_frequency, current_band, downlink_frequency+delta_duplex); + + AssertFatal(current_band != 0, "Can't find EUTRA band for frequency %"PRIu64" and duplex_spacing %u\n", downlink_frequency, delta_duplex); + + return current_band; +} + const size_t nr_bandtable_size = sizeof(nr_bandtable) / sizeof(nr_bandentry_t); int NRRIV2BW(int locationAndBandwidth,int N_RB) { diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 6389c2c094..acb852857e 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -50,6 +50,7 @@ typedef struct nr_bandentry_s { extern const size_t nr_bandtable_size; extern nr_bandentry_t nr_bandtable[]; +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex); int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize); diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index 870f1546f6..deb74294d7 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -64,6 +64,7 @@ #define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" #define CONFIG_HLP_TADV "Set timing_advance\n" #define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" +#define CONFIG_HLP_ULOFF "Set the uplink frequnecy offset for all component carriers\n" #define CONFIG_HLP_CHOFF "Channel id offset\n" #define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n" #define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n" diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 916d01c3e1..0ef6f1a785 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -438,13 +438,17 @@ int main( int argc, char **argv ) { set_options(CC_id, UE[CC_id]); - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - if(mac->if_module != NULL && mac->if_module->phy_config_request != NULL) - mac->if_module->phy_config_request(&mac->phy_config); + if (get_softmodem_params()->sa) + nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms,downlink_frequency[CC_id][0],uplink_frequency_offset[CC_id][0]); + else{ + NR_UE_MAC_INST_t *mac = get_mac_inst(0); + if(mac->if_module != NULL && mac->if_module->phy_config_request != NULL) + mac->if_module->phy_config_request(&mac->phy_config); - fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; + fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; - nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); + nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); + } init_symbol_rotation(&UE[CC_id]->frame_parms); init_nr_ue_vars(UE[CC_id], 0, abstraction_flag); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 153f648865..42c2774729 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -56,7 +56,8 @@ {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&(UE->UE_fo_compensation), defintval:0, TYPE_INT, 0}, \ {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF,TYPE_UINT64,0}, \ + {"D" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF,TYPE_UINT64,0}, \ + {"U" , CONFIG_HLP_ULOFF, 0, iptr:&(uplink_frequency_offset[0][0]), defuintval:0, TYPE_INT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ {"m" , CONFIG_HLP_MUSSB, 0, u8ptr:&(fp->numerology_index), defintval:0, TYPE_UINT8, 0}, \ {"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:106, TYPE_UINT, 0}, \ diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 0e6b253c2b..4d31230290 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -46,42 +46,6 @@ #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" -static -uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) -{ - const uint64_t dl_freq_khz = downlink_frequency / 1000; - const int32_t delta_duplex_khz = delta_duplex / 1000; - - uint64_t center_freq_diff_khz = 999999999999999999; // 2^64 - uint16_t current_band = 0; - - for (int ind = 0; ind < nr_bandtable_size; ind++) { - - LOG_D(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min, nr_bandtable[ind].ul_min); - - if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max) - continue; - - int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min; - - if (current_offset_khz != delta_duplex_khz) - continue; - - uint64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; - - if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ - current_band = nr_bandtable[ind].band; - center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); - } - } - - LOG_I(PHY, "DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n", - downlink_frequency, current_band, downlink_frequency+delta_duplex); - - AssertFatal(current_band != 0, "Can't find EUTRA band for frequency %"PRIu64" and duplex_spacing %u\n", downlink_frequency, delta_duplex); - - return current_band; -} int l1_north_init_gNB() { diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index bacc671adc..7ba581b092 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -20,6 +20,7 @@ */ #include "phy_init.h" +#include "common/utils/nr/nr_common.h" #include "common/utils/LOG/log.h" #include "LAYER2/NR_MAC_gNB/mac_proto.h" @@ -27,6 +28,18 @@ uint32_t nr_subcarrier_spacing[MAX_NUM_SUBCARRIER_SPACING] = {15e3, 30e3, 60e3, 120e3, 240e3}; uint16_t nr_slots_per_subframe[MAX_NUM_SUBCARRIER_SPACING] = {1, 2, 4, 8, 16}; +void set_Lmax(NR_DL_FRAME_PARMS *fp) { + // definition of Lmax according to ts 38.213 section 4.1 + if (fp->dl_CarrierFreq < 6e9) { + if(fp->frame_type && (fp->ssb_type==2)) + fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8; + else + fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8; + } else { + fp->Lmax = 64; + } +} + int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp) { @@ -224,15 +237,7 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, fp->Ncp = Ncp; - // definition of Lmax according to ts 38.213 section 4.1 - if (fp->dl_CarrierFreq < 6e9) { - if(fp->frame_type && (fp->ssb_type==2)) - fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8; - else - fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8; - } else { - fp->Lmax = 64; - } + set_Lmax(fp); fp->N_ssb = 0; int num_tx_ant = cfg->carrier_config.num_tx_ant.value; @@ -316,15 +321,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco); - // definition of Lmax according to ts 38.213 section 4.1 - if (fp->dl_CarrierFreq < 6e9) { - if(fp->frame_type && (fp->ssb_type==2)) - fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8; - else - fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8; - } else { - fp->Lmax = 64; - } + set_Lmax(fp); fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask; @@ -335,6 +332,44 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, return 0; } +void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t delta_duplex) { + + LOG_I(PHY,"SA init parameters. DL freq %lu UL offset %d SSB numerology %d N_RB_DL %d\n", + downlink_frequency, + delta_duplex, + frame_parms->numerology_index, + frame_parms->N_RB_DL); + + frame_parms->dl_CarrierFreq = downlink_frequency; + frame_parms->ul_CarrierFreq = downlink_frequency + delta_duplex; + frame_parms->freq_range = (frame_parms->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; + frame_parms->N_RB_UL = frame_parms->N_RB_UL; + + frame_parms->nr_band = get_band(downlink_frequency, delta_duplex); + frame_parms->frame_type = get_frame_type(frame_parms->nr_band, frame_parms->numerology_index); + + frame_parms->Ncp = NORMAL; + set_scs_parameters(frame_parms, frame_parms->numerology_index, frame_parms->N_RB_DL); + set_Lmax(frame_parms); + + frame_parms->slots_per_frame = 10* frame_parms->slots_per_subframe; + frame_parms->symbols_per_slot = ((frame_parms->Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats + frame_parms->samples_per_subframe_wCP = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot * frame_parms->slots_per_subframe; + frame_parms->samples_per_frame_wCP = 10 * frame_parms->samples_per_subframe_wCP; + frame_parms->samples_per_slot_wCP = frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; + frame_parms->samples_per_slotN0 = (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * frame_parms->symbols_per_slot; + frame_parms->samples_per_slot0 = frame_parms->nb_prefix_samples0 + ((frame_parms->symbols_per_slot-1)*frame_parms->nb_prefix_samples) + (frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size); + frame_parms->samples_per_subframe = (frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size) * 2 + + (frame_parms->nb_prefix_samples + frame_parms->ofdm_symbol_size) * (frame_parms->symbols_per_slot * frame_parms->slots_per_subframe - 2); + frame_parms->get_samples_per_slot = &get_samples_per_slot; + frame_parms->get_samples_slot_timestamp = &get_samples_slot_timestamp; + frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe; + + exit(1); + +} + + void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp) { LOG_I(PHY,"fp->scs=%d\n",fp->subcarrier_spacing); diff --git a/openair1/PHY/INIT/phy_init.h b/openair1/PHY/INIT/phy_init.h index 9c474264c8..d1b52df4b2 100644 --- a/openair1/PHY/INIT/phy_init.h +++ b/openair1/PHY/INIT/phy_init.h @@ -389,12 +389,12 @@ void phy_config_request(PHY_Config_t *phy_config); void phy_config_update_sib2_request(PHY_Config_t *phy_config); void phy_config_update_sib13_request(PHY_Config_t *phy_config); - int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf); void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms); int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp); int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms); int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band); +void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset); int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB,uint8_t abstraction_flag); void init_nr_ue_transport(PHY_VARS_NR_UE *ue,int abstraction_flag); void init_N_TA_offset(PHY_VARS_NR_UE *ue); From 0862988c23c0c0e85f612c9c6c57248346ff7643 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 24 Mar 2021 10:36:27 +0100 Subject: [PATCH 019/185] initial sync ok if SSB in the middle --- openair1/PHY/INIT/nr_parms.c | 7 +++---- openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/sss_nr.c | 9 +++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 7ba581b092..0595bb2ab5 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -320,7 +320,6 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, sco = config->ssb_table.ssb_subcarrier_offset; fp->ssb_start_subcarrier = (12 * config->ssb_table.ssb_offset_point_a + sco); - set_Lmax(fp); fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask; @@ -343,7 +342,7 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink frame_parms->dl_CarrierFreq = downlink_frequency; frame_parms->ul_CarrierFreq = downlink_frequency + delta_duplex; frame_parms->freq_range = (frame_parms->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; - frame_parms->N_RB_UL = frame_parms->N_RB_UL; + frame_parms->N_RB_UL = frame_parms->N_RB_DL; frame_parms->nr_band = get_band(downlink_frequency, delta_duplex); frame_parms->frame_type = get_frame_type(frame_parms->nr_band, frame_parms->numerology_index); @@ -365,8 +364,8 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink frame_parms->get_samples_slot_timestamp = &get_samples_slot_timestamp; frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe; - exit(1); - + // setting initial ssb start subcarrier to have SSBs at BW center + frame_parms->ssb_start_subcarrier = ((frame_parms->N_RB_DL>>1)-10)*12; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 189ad53efa..dbf957992e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -348,7 +348,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames) } } else { - ret = -1; + ret = -1; } /* Consider this is a false detection if the offset is > 1000 Hz diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 66296910fc..9339f3974d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -318,7 +318,7 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR], uint8_t doPss, uint8_t doSss, - uint8_t subframe) // add flag to indicate extracting only PSS, only SSS, or both + uint8_t subframe) // add flag to indicate extracting only PSS, only SSS, or both { uint8_t aarx; int32_t *pss_rxF,*pss_rxF_ext; @@ -329,8 +329,8 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, for (aarx=0; aarxnb_antennas_rx; aarx++) { - pss_symbol = 0; - sss_symbol = SSS_SYMBOL_NB-PSS_SYMBOL_NB; + pss_symbol = 0; + sss_symbol = SSS_SYMBOL_NB-PSS_SYMBOL_NB; rxdataF = ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; @@ -343,6 +343,7 @@ int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue, sss_rxF_ext = &sss_ext[aarx][0]; unsigned int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; + if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; for (int i=0; i < LENGTH_PSS_NR; i++) { @@ -401,7 +402,7 @@ int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR], - uint8_t subframe) + uint8_t subframe) { return do_pss_sss_extract_nr(phy_vars_ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe); } From a788c696d8ecb5c3cfcc2673d022da52da629e4e Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 25 Mar 2021 10:56:19 +0100 Subject: [PATCH 020/185] ssb start subcarrier in ssb indication for reception of sib1 --- .../nfapi/public_inc/fapi_nr_ue_constants.h | 2 +- .../nfapi/public_inc/fapi_nr_ue_interface.h | 6 ++--- openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c | 2 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 13 ++++++----- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 3 ++- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 11 +++------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 3 +-- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 22 ++++++++++++------- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h | 10 ++++++++- 9 files changed, 41 insertions(+), 31 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h index 0a83c1a27f..869b4d16ff 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h @@ -14,7 +14,7 @@ /// RX_IND -#define FAPI_NR_RX_PDU_TYPE_MIB 0x01 +#define FAPI_NR_RX_PDU_TYPE_SSB 0x01 #define FAPI_NR_RX_PDU_TYPE_SIB 0x02 #define FAPI_NR_RX_PDU_TYPE_DLSCH 0x03 #define FAPI_NR_DCI_IND 0x04 diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 9df9be4cbd..d087e1467b 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -111,8 +111,8 @@ typedef struct { uint8_t ssb_index; uint8_t ssb_length; uint16_t cell_id; - -} fapi_nr_mib_pdu_t; + uint16_t ssb_start_subcarrier; +} fapi_nr_ssb_pdu_t; typedef struct { uint32_t pdu_length; @@ -124,7 +124,7 @@ typedef struct { uint8_t pdu_type; union { fapi_nr_pdsch_pdu_t pdsch_pdu; - fapi_nr_mib_pdu_t mib_pdu; + fapi_nr_ssb_pdu_t ssb_pdu; fapi_nr_sib_pdu_t sib_pdu; }; } fapi_nr_rx_indication_body_t; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 3e1fd68b72..f9c3cadbae 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -614,7 +614,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, uint16_t number_pdus = 1; nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_MIB, gNB_id, ue, NULL, number_pdus); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, gNB_id, ue, NULL, number_pdus); if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication, NULL); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 14c174c2c0..835c839710 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -139,12 +139,13 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[harq_pid]->b; rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[harq_pid]->TBS / 8; break; - case FAPI_NR_RX_PDU_TYPE_MIB: - rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output; - rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.additional_bits = ue->pbch_vars[gNB_id]->xtra_byte; - rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_index = frame_parms->ssb_index; - rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_length = frame_parms->Lmax; - rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.cell_id = frame_parms->Nid_cell; + case FAPI_NR_RX_PDU_TYPE_SSB: + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.additional_bits = ue->pbch_vars[gNB_id]->xtra_byte; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_index = frame_parms->ssb_index; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_length = frame_parms->Lmax; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.cell_id = frame_parms->Nid_cell; + rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; break; default: break; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 14d1ea63fb..44df0c54e1 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -53,7 +53,8 @@ int8_t nr_ue_decode_mib( uint8_t extra_bits, uint32_t ssb_length, uint32_t ssb_index, - void *pduP, + void *pduP, + uint16_t ssb_start_subcarrier, uint16_t cell_id ); /**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 0d7bbacece..421d535b2c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -99,6 +99,7 @@ int8_t nr_ue_decode_mib(module_id_t module_id, uint32_t ssb_length, uint32_t ssb_index, void *pduP, + uint16_t ssb_start_subcarrier, uint16_t cell_id) { LOG_I(MAC,"[L2][MAC] decode mib\n"); @@ -149,14 +150,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, // TODO these values shouldn't be taken from SCC in SA uint8_t scs_ssb = *scc->ssbSubcarrierSpacing; uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - int scs_scaling = 1<downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) - scs_scaling = scs_scaling*3; - if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) - scs_scaling = scs_scaling>>2; - uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); - uint16_t ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); + uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; get_type0_PDCCH_CSS_config_parameters(&mac->type0_PDCCH_CSS_config, frame, @@ -167,7 +162,7 @@ int8_t nr_ue_decode_mib(module_id_t module_id, scs_ssb, frequency_range, ssb_index, - absolute_diff/(12*scs_scaling)-10); + ssb_offset_point_a); mac->type0_pdcch_ss_mux_pattern = mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 68137c3aa5..a82d7e4549 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -528,7 +528,6 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - LOG_D(MAC,"Schedule_nr_sib1: frameP = %i, slotP = %i\n", frameP, slotP); // TODO: Get these values from RRC const int CC_id = 0; @@ -565,7 +564,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) (type0_PDCCH_CSS_config->num_rbs > 0) && (type0_PDCCH_CSS_config->active == true)) { - LOG_D(MAC,"> SIB1 transmission\n"); + LOG_D(MAC,"Schedule_nr_sib1: frameP = %i, slotP = %i\n", frameP, slotP); // Get SIB1 uint8_t sib1_payload[NR_MAX_SIB_LENGTH/8]; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 51d279b7d1..ba5d679c1f 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -47,7 +47,11 @@ const char *dl_indication_type[] = {"MIB", "SIB", "DLSCH", "DCI", "RAR"}; static nr_ue_if_module_t *nr_ue_if_module_inst[MAX_IF_MODULES]; // L2 Abstraction Layer -int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t *pduP, unsigned int additional_bits, uint32_t ssb_index, uint32_t ssb_length, uint16_t cell_id){ +int handle_bcch_bch(module_id_t module_id, int cc_id, + unsigned int gNB_index, uint8_t *pduP, + unsigned int additional_bits, + uint32_t ssb_index, uint32_t ssb_length, + uint16_t ssb_start_subcarrier, uint16_t cell_id){ return nr_ue_decode_mib(module_id, cc_id, @@ -55,7 +59,8 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, ui additional_bits, ssb_length, // Lssb = 64 is not support ssb_index, - pduP, + pduP, + ssb_start_subcarrier, cell_id); } @@ -155,14 +160,15 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ switch(dl_info->rx_ind->rx_indication_body[i].pdu_type){ - case FAPI_NR_RX_PDU_TYPE_MIB: + case FAPI_NR_RX_PDU_TYPE_SSB: ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.additional_bits, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.ssb_index, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.ssb_length, - (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_MIB; + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.additional_bits, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_index, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_length, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_start_subcarrier, + (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; break; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index e78529d437..449c7bf890 100755 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -221,7 +221,15 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq); \param ssb_index SSB index within 0 - (L_ssb-1) corresponding to 38.331 ch.13 parameter i \param ssb_length corresponding to L1 parameter L_ssb \param cell_id cell id */ -int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t *pduP, unsigned int additional_bits, uint32_t ssb_index, uint32_t ssb_length, uint16_t cell_id); +int handle_bcch_bch(module_id_t module_id, + int cc_id, + unsigned int gNB_index, + uint8_t *pduP, + unsigned int additional_bits, + uint32_t ssb_index, + uint32_t ssb_length, + uint16_t ssb_start_subcarrier, + uint16_t cell_id); // TODO check /**\brief handle BCCH-DL-SCH message from dl_indication From 1d2e5cabd87ca1ca40460eead61bc1c2ccb12e86 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 26 Mar 2021 14:41:05 +0100 Subject: [PATCH 021/185] Closing review comments MR 1081 --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 80 ++++---- .../nr_dl_channel_estimation.c | 182 +++++++++--------- openair1/SIMULATION/NR_PHY/ulsim.c | 4 +- 3 files changed, 132 insertions(+), 134 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 0bfa5c576a..f0ec764922 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -208,7 +208,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch, ul_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //for (int i= 0; i<8; i++) @@ -239,7 +239,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch, ul_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //printf("ul_ch addr %p\n",ul_ch); @@ -273,12 +273,12 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //for (int i= 0; i<16; i++) //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ul_ch+=8; + ul_ch += 8; - for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pusch-3); pilot_cnt+=2) { + for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pusch-3); pilot_cnt += 2) { ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -291,7 +291,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch, ul_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //printf("ul_ch addr %p\n",ul_ch); @@ -311,10 +311,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //for (int i= 0; i<16; i++) //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ul_ch+=8; + ul_ch += 8; } @@ -333,7 +333,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //for (int i= 0; i<8; i++) //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -349,10 +349,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ul_ch+=8; + ul_ch += 8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -421,7 +421,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #ifdef DEBUG_PUSCH ul_ch = (int16_t *)&ul_ch_estimates[aarx][ch_offset]; for(uint16_t idxP=0; idxP>15); ul_ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; - ul_ch+=2; + pil += 2; + ul_ch += 2; re_offset = (re_offset + 1)%gNB->frame_parms.ofdm_symbol_size; ch_offset++; - for (re_cnt = 1; re_cnt < (nb_rb_pusch*NR_NB_SC_PER_RB) - 5; re_cnt+=6){ + for (re_cnt = 1; re_cnt < (nb_rb_pusch*NR_NB_SC_PER_RB) - 5; re_cnt += 6){ rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -452,8 +452,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch[0] = ch_l[0]; ul_ch[1] = ch_l[1]; - pil+=2; - ul_ch+=2; + pil += 2; + ul_ch += 2; ch_offset++; multadd_real_four_symbols_vector_complex_scalar(filt8_ml2, @@ -472,17 +472,17 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch_r, ul_ch); - //for (int re_idx = 0; re_idx < 8; re_idx+=2) + //for (int re_idx = 0; re_idx < 8; re_idx += 2) //printf("ul_ch = %d + j*%d\n", ul_ch[re_idx], ul_ch[re_idx+1]); - ul_ch+=8; - ch_offset+=4; + ul_ch += 8; + ch_offset += 4; ul_ch[0] = ch_r[0]; ul_ch[1] = ch_r[1]; - pil+=2; - ul_ch+=2; + pil += 2; + ul_ch += 2; ch_offset++; re_offset = (re_offset + 1)%gNB->frame_parms.ofdm_symbol_size; @@ -498,7 +498,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch[0] = ch_l[0]; ul_ch[1] = ch_l[1]; - ul_ch+=2; + ul_ch += 2; ch_offset++; multadd_real_four_symbols_vector_complex_scalar(filt8_rr1, @@ -516,46 +516,46 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB - for (pilot_cnt=0; pilot_cnt<6*nb_rb_pusch; pilot_cnt+=6) { + for (pilot_cnt=0; pilot_cnt<6*nb_rb_pusch; pilot_cnt += 6) { ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0]/=6; @@ -563,29 +563,29 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; - ul_ch+=24; + ul_ch += 24; } } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB - for (pilot_cnt=0; pilot_cnt<4*nb_rb_pusch; pilot_cnt+=4) { + for (pilot_cnt=0; pilot_cnt<4*nb_rb_pusch; pilot_cnt += 4) { ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -593,21 +593,21 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0]>>=2; - ch[1]>>=2; + ch[0] /=4 ; + ch[1] /=4 ; ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; - ul_ch+=24; + ul_ch += 24; } } #ifdef DEBUG_PDSCH ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; for(uint16_t idxP=0; idxP>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -110,29 +110,29 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; - for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt+=3) { + for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt += 3) { // if (pilot_cnt == 30) // rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k)]; @@ -146,14 +146,14 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -161,13 +161,13 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -175,14 +175,14 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - current_ssb->c_re +=ch[0]; - current_ssb->c_im +=ch[1]; + current_ssb->c_re += ch[0]; + current_ssb->c_im += ch[1]; #ifdef DEBUG_CH printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -309,7 +309,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -327,7 +327,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -342,12 +342,12 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; - dl_ch+=24; + dl_ch += 24; - for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt+=3) { + for (pilot_cnt=3; pilot_cnt<(3*20); pilot_cnt += 3) { // if (pilot_cnt == 30) // rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k)]; @@ -373,7 +373,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, //for (int i= 0; i<8; i++) // printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -388,7 +388,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; @@ -404,10 +404,10 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; + pil += 2; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; - dl_ch+=24; + dl_ch += 24; } @@ -547,8 +547,8 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; - rxF+=8; + pil += 2; + rxF += 8; //for (int i= 0; i<8; i++) //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); @@ -561,8 +561,8 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; - rxF+=8; + pil += 2; + rxF += 8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -580,14 +580,14 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, for (int m =0; m<12; m++) printf("data : dl_ch -> (%d,%d)\n",dl_ch[0+2*m],dl_ch[1+2*m]); #endif - pil+=2; - rxF+=8; - dl_ch+=24; - k+=12; + pil += 2; + rxF += 8; + dl_ch += 24; + k += 12; - for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt+=3) { + for (pilot_cnt=3; pilot_cnt<(3*nb_rb_coreset); pilot_cnt += 3) { if (k >= ue->frame_parms.ofdm_symbol_size){ k-=ue->frame_parms.ofdm_symbol_size; @@ -606,8 +606,8 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, //for (int i= 0; i<8; i++) // printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i)); - pil+=2; - rxF+=8; + pil += 2; + rxF += 8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -618,8 +618,8 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; - rxF+=8; + pil += 2; + rxF += 8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -632,10 +632,10 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 16); - pil+=2; - rxF+=8; - dl_ch+=24; - k+=12; + pil += 2; + rxF += 8; + dl_ch += 24; + k += 12; } @@ -690,11 +690,11 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, uint16_t rb_offset = (bwp_start_subcarrier - ue->frame_parms.first_carrier_offset) / 12 - BWPStart; uint8_t config_type = ue->dmrs_DownlinkConfig.pdsch_dmrs_type; int8_t delta = get_delta(p, config_type); + nushift = delta; + ue->frame_parms.nushift = nushift; nr_pdsch_dmrs_rx(ue,Ns,ue->nr_gold_pdsch[eNB_offset][Ns][symbol][0], &pilot[0],1000,0,nb_rb_pdsch+rb_offset); if (config_type == pdsch_dmrs_type1 && ue->fd_lin_interpolation == 1){ - nushift = (p>>1)&1; - ue->frame_parms.nushift = nushift; switch (delta) { case 0://port 0,1 @@ -733,8 +733,6 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, break; } } else if (ue->fd_lin_interpolation == 1) {//pdsch_dmrs_type2 - nushift = delta; - ue->frame_parms.nushift = nushift; switch (delta) { case 0://port 0,1 fl = filt8_l2;//left interpolation Filter should be fml @@ -806,7 +804,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //for (int i= 0; i<8; i++) @@ -821,7 +819,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; //printf("dl_ch addr %p\n",dl_ch); @@ -839,14 +837,14 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, //for (int i= 0; i<16; i++) //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - dl_ch+=8; + dl_ch += 8; - for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pdsch-3); pilot_cnt+=2) { + for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pdsch-3); pilot_cnt += 2) { //if ((pilot_cnt%6)==0) - //dl_ch+=4; + //dl_ch += 4; //printf("re_offset %d\n",re_offset); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -859,7 +857,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -872,10 +870,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - dl_ch+=8; + dl_ch += 8; } @@ -893,7 +891,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, //for (int i= 0; i<8; i++) //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -908,10 +906,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - dl_ch+=8; + dl_ch += 8; ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -986,7 +984,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, printf("pilot 0 : rxF - > (%d,%d) addr %p ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],&rxF[0],ch_l[0],ch_l[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -1005,13 +1003,13 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch_l[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -1025,20 +1023,20 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - dl_ch+=12; + dl_ch += 12; dl_ch[0+2*nushift] = ch[0]; dl_ch[1+2*nushift] = ch[1]; dl_ch[2+2*nushift] = ch[0]; dl_ch[3+2*nushift] = ch[1]; - dl_ch+=4; + dl_ch += 4; - for (pilot_cnt=4; pilot_cnt<4*nb_rb_pdsch; pilot_cnt+=4) { + for (pilot_cnt=4; pilot_cnt<4*nb_rb_pdsch; pilot_cnt += 4) { multadd_real_vector_complex_scalar(fml, ch, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -1048,7 +1046,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, printf("pilot %u : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch_l[0],ch_l[1],pil[0],pil[1]); #endif - pil+=2; + pil += 2; re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -1066,7 +1064,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - dl_ch+=8; + dl_ch += 8; dl_ch[0+2*nushift] = ch[0]; dl_ch[1+2*nushift] = ch[1]; dl_ch[2+2*nushift] = ch[0]; @@ -1077,13 +1075,13 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - pil+=2; + pil += 2; re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch_l[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -1101,12 +1099,12 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - dl_ch+=12; + dl_ch += 12; dl_ch[0+2*nushift] = ch[0]; dl_ch[1+2*nushift] = ch[1]; dl_ch[2+2*nushift] = ch[0]; dl_ch[3+2*nushift] = ch[1]; - dl_ch+=4; + dl_ch += 4; } // Treat last 2 pilots specially (right edge) @@ -1187,48 +1185,48 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, } } } - else if (config_type==pdsch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + else if (config_type == pdsch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB - for (pilot_cnt=0; pilot_cnt<6*nb_rb_pdsch; pilot_cnt+=6) { + for (pilot_cnt=0; pilot_cnt<6*nb_rb_pdsch; pilot_cnt += 6) { ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0]/=6; @@ -1236,29 +1234,29 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; - dl_ch+=24; + dl_ch += 24; } } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB - for (pilot_cnt=0; pilot_cnt<4*nb_rb_pdsch; pilot_cnt+=4) { + for (pilot_cnt=0; pilot_cnt<4*nb_rb_pdsch; pilot_cnt += 4) { ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -1266,21 +1264,21 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - pil+=2; + pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0]>>=2; - ch[1]>>=2; + ch[0] /=4 ; + ch[1] /=4 ; ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; - dl_ch+=24; + dl_ch += 24; } } #ifdef DEBUG_PDSCH dl_ch = (int16_t *)&dl_ch_estimates[p*ue->frame_parms.nb_antennas_rx+aarx][ch_offset]; for(uint16_t idxP=0; idxPcommon_vars.rxdata[0][slot_offset])[i], ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]); - mod_order = nr_get_Qm_ul(Imcs, 0); - code_rate = nr_get_code_rate_ul(Imcs, 0); + mod_order = nr_get_Qm_ul(Imcs, mcs_table); + code_rate = nr_get_code_rate_ul(Imcs, mcs_table); } for (SNR = snr0; SNR < snr1; SNR += snr_step) { From 032a850c23667f78d3bfba2ba791087fd39cfbc7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 26 Mar 2021 15:46:51 +0100 Subject: [PATCH 022/185] getting rid of dl and ul_bwp_dedicated in config request --- .../nfapi/public_inc/fapi_nr_ue_interface.h | 6 - openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 28 ++-- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 130 ++++++++++-------- 3 files changed, 93 insertions(+), 71 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index d087e1467b..afa8325ea1 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -1058,12 +1058,6 @@ typedef struct { fapi_nr_tdd_table_t tdd_table; fapi_nr_prach_config_t prach_config; - fapi_nr_dl_bwp_common_config_t dl_bwp_common; - fapi_nr_dl_bwp_dedicated_config_t dl_bwp_dedicated; - - fapi_nr_ul_bwp_common_config_t ul_bwp_common; - fapi_nr_ul_bwp_dedicated_config_t ul_bwp_dedicated; - } fapi_nr_config_request_t; #endif diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 421d535b2c..91b2dc509b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -869,7 +869,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */ dlsch_config_pdu_1_1->n_dmrs_cdm_groups = 1; /* VRB_TO_PRB_MAPPING */ - if (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.resource_allocation != 0) + if ((pdsch_config->resourceAllocation == 1) && (pdsch_config->vrb_ToPRB_Interleaver != NULL)) dlsch_config_pdu_1_1->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; /* PRB_BUNDLING_SIZE_IND */ dlsch_config_pdu_1_1->prb_bundling_size_ind = dci->prb_bundling_size_indicator.val; @@ -928,11 +928,22 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ // according to TS 38.213 Table 9.2.3-1 NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; - dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; + dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = + mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; + /* ANTENNA_PORTS */ uint8_t n_codewords = 1; // FIXME!!! - if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.max_length == 1)){ + long *max_length = NULL; + long *dmrs_type = NULL; + if (pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA) { + max_length = pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength; + dmrs_type = pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type; + } + if (pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeB) { + max_length = pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->maxLength; + dmrs_type = pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup->dmrs_Type; + } + if ((dmrs_type == NULL) && (max_length == NULL)){ // Table 7.3.1.2.2-1: Antenna port(s) (1000 + DMRS port), dmrs-Type=1, maxLength=1 dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_1[dci->antenna_ports.val][0]; dlsch_config_pdu_1_1->dmrs_ports[0] = table_7_3_2_3_3_1[dci->antenna_ports.val][1]; @@ -940,8 +951,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->dmrs_ports[2] = table_7_3_2_3_3_1[dci->antenna_ports.val][3]; dlsch_config_pdu_1_1->dmrs_ports[3] = table_7_3_2_3_3_1[dci->antenna_ports.val][4]; } - if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.max_length == 2)){ + if ((dmrs_type == NULL) && (max_length != NULL)){ // Table 7.3.1.2.2-2: Antenna port(s) (1000 + DMRS port), dmrs-Type=1, maxLength=2 if (n_codewords == 1) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_2_oneCodeword[dci->antenna_ports.val][0]; @@ -964,8 +974,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->n_front_load_symb = table_7_3_2_3_3_2_twoCodeword[dci->antenna_ports.val][9]; } } - if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 2) && - (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.max_length == 1)){ + if ((dmrs_type != NULL) && (max_length == NULL)){ // Table 7.3.1.2.2-3: Antenna port(s) (1000 + DMRS port), dmrs-Type=2, maxLength=1 if (n_codewords == 1) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_3_oneCodeword[dci->antenna_ports.val][0]; @@ -984,8 +993,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->dmrs_ports[5] = table_7_3_2_3_3_3_twoCodeword[dci->antenna_ports.val][6]; } } - if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 2) && - (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.max_length == 2)){ + if ((dmrs_type != NULL) && (max_length != NULL)){ // Table 7.3.1.2.2-4: Antenna port(s) (1000 + DMRS port), dmrs-Type=2, maxLength=2 if (n_codewords == 1) { dlsch_config_pdu_1_1->n_dmrs_cdm_groups = table_7_3_2_3_3_4_oneCodeword[dci->antenna_ports.val][0]; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index ad1958ef33..0b58ea4041 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -145,14 +145,25 @@ fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int sl void ul_layers_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci) { - fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated; + NR_ServingCellConfigCommon_t *scc = mac->scc; NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; + long transformPrecoder; + if (pusch_Config->transformPrecoder) + transformPrecoder = *pusch_Config->transformPrecoder; + else { + if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder) + transformPrecoder = NR_PUSCH_Config__transformPrecoder_enabled; + else + transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; + } + + /* PRECOD_NBR_LAYERS */ - if ((pusch_config_dedicated->tx_config == tx_config_nonCodebook)); + if ((*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook)); // 0 bits if the higher layer parameter txConfig = nonCodeBook - if ((pusch_config_dedicated->tx_config == tx_config_codebook)){ + if ((*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook)){ uint8_t n_antenna_port = 0; //FIXME!!! @@ -161,43 +172,43 @@ void ul_layers_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_con if (n_antenna_port == 4){ // 4 antenna port and the higher layer parameter txConfig = codebook // Table 7.3.1.1.2-2: transformPrecoder=disabled and maxRank = 2 or 3 or 4 - if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) - && ((pusch_config_dedicated->max_rank == 2) || - (pusch_config_dedicated->max_rank == 3) || - (pusch_config_dedicated->max_rank == 4))){ + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) + && ((*pusch_Config->maxRank == 2) || + (*pusch_Config->maxRank == 3) || + (*pusch_Config->maxRank == 4))){ - if (pusch_config_dedicated->codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_fullyAndPartialAndNonCoherent) { pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][0]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][1]; } - if (pusch_config_dedicated->codebook_subset == codebook_subset_partialAndNonCoherent){ + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent){ pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][2]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][3]; } - if (pusch_config_dedicated->codebook_subset == codebook_subset_nonCoherent){ + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent){ pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][4]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][5]; } } // Table 7.3.1.1.2-3: transformPrecoder= enabled, or transformPrecoder=disabled and maxRank = 1 - if (((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) - || (pusch_config_dedicated->transform_precoder == transform_precoder_disabled)) - && (pusch_config_dedicated->max_rank == 1)){ + if (((transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled) + || (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled)) + && (*pusch_Config->maxRank == 1)){ - if (pusch_config_dedicated->codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_fullyAndPartialAndNonCoherent) { pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][6]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][7]; } - if (pusch_config_dedicated->codebook_subset == codebook_subset_partialAndNonCoherent){ + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_partialAndNonCoherent){ pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][8]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][9]; } - if (pusch_config_dedicated->codebook_subset == codebook_subset_nonCoherent){ + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent){ pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][10]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][11]; } @@ -206,14 +217,14 @@ void ul_layers_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_con if (n_antenna_port == 4){ // 2 antenna port and the higher layer parameter txConfig = codebook // Table 7.3.1.1.2-4: transformPrecoder=disabled and maxRank = 2 - if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && (pusch_config_dedicated->max_rank == 2)){ + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank == 2)){ - if (pusch_config_dedicated->codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_fullyAndPartialAndNonCoherent) { pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][12]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][13]; } - if (pusch_config_dedicated->codebook_subset == codebook_subset_nonCoherent){ + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent){ pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][14]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][15]; } @@ -221,16 +232,16 @@ void ul_layers_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_con } // Table 7.3.1.1.2-5: transformPrecoder= enabled, or transformPrecoder= disabled and maxRank = 1 - if (((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) - || (pusch_config_dedicated->transform_precoder == transform_precoder_disabled)) - && (pusch_config_dedicated->max_rank == 1)){ + if (((transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled) + || (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled)) + && (*pusch_Config->maxRank == 1)){ - if (pusch_config_dedicated->codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_fullyAndPartialAndNonCoherent) { pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][16]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][17]; } - if (pusch_config_dedicated->codebook_subset == codebook_subset_nonCoherent){ + if (*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent){ pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][18]; pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][19]; } @@ -241,7 +252,7 @@ void ul_layers_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_con /*-------------------- Changed to enable Transform precoding in RF SIM------------------------------------------------*/ - if (pusch_config_pdu->transform_precoding == transform_precoder_enabled) { + /*if (pusch_config_pdu->transform_precoding == transform_precoder_enabled) { pusch_config_dedicated->transform_precoder = transform_precoder_enabled; @@ -265,15 +276,7 @@ void ul_layers_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_con } } else - pusch_config_dedicated->transform_precoder = transform_precoder_disabled; - - // mapping type b configured from RRC. TBD: Mapping type b is not handled in this function. - if ((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_b.dmrs_type == 1) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_b.max_length == 1)) { // tables 7.3.1.1.2-6 - pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; - pusch_config_pdu->dmrs_ports = dci->antenna_ports.val; - } + pusch_config_dedicated->transform_precoder = transform_precoder_disabled;*/ } // todo: this function shall be reviewed completely because of the many comments left by the author @@ -281,27 +284,47 @@ void ul_ports_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_conf /* ANTENNA_PORTS */ uint8_t rank = 0; // We need to initialize rank FIXME!!! - fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated; - if ((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-6 + NR_ServingCellConfigCommon_t *scc = mac->scc; + NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; + + long transformPrecoder; + if (pusch_Config->transformPrecoder) + transformPrecoder = *pusch_Config->transformPrecoder; + else { + if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder) + transformPrecoder = NR_PUSCH_Config__transformPrecoder_enabled; + else + transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; + } + long *max_length = NULL; + long *dmrs_type = NULL; + if (pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA) { + max_length = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->maxLength; + dmrs_type = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup->dmrs_Type; + } + else { + max_length = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->maxLength; + dmrs_type = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->dmrs_Type; + } + + + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled) && + (dmrs_type == NULL) && (max_length == NULL)) { // tables 7.3.1.1.2-6 pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC pusch_config_pdu->dmrs_ports = dci->antenna_ports.val; //TBC } - if ((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-7 + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled) && + (dmrs_type == NULL) && (max_length != NULL)) { // tables 7.3.1.1.2-7 pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 3)?(dci->antenna_ports.val-4):(dci->antenna_ports.val); //TBC //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports > 3)?2:1; //FIXME } - if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-8/9/10/11 + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && + (dmrs_type == NULL) && (max_length == NULL)) { // tables 7.3.1.1.2-8/9/10/11 if (rank == 1) { pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC @@ -333,9 +356,8 @@ void ul_ports_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_conf } } - if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-12/13/14/15 + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && + (dmrs_type == NULL) && (max_length != NULL)) { // tables 7.3.1.1.2-12/13/14/15 if (rank == 1){ pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC @@ -371,9 +393,9 @@ void ul_ports_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_conf } } - if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 2) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-16/17/18/19 + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && + (dmrs_type != NULL) && + (max_length == NULL)) { // tables 7.3.1.1.2-16/17/18/19 if (rank == 1){ pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?((dci->antenna_ports.val > 5)?3:2):1; //TBC @@ -405,9 +427,8 @@ void ul_ports_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_conf } } - if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 2) && - (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-20/21/22/23 + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && + (dmrs_type != NULL) && (max_length != NULL)) { // tables 7.3.1.1.2-20/21/22/23 if (rank == 1){ pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_20[dci->antenna_ports.val][0]; //TBC @@ -563,7 +584,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, int target_ss; bool valid_ptrs_setup = 0; uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated; NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; // Basic sanity check for MCS value to check for a false or erroneous DCI @@ -646,7 +666,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } /* FREQ_HOPPING_FLAG */ - if ((pusch_config_dedicated->resource_allocation != 0) && (pusch_config_dedicated->frequency_hopping !=0)){ + if ((pusch_Config->frequencyHopping!=NULL) && (pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0)){ pusch_config_pdu->frequency_hopping = dci->frequency_hopping_flag.val; } From a83265dfb1fcd6b82951f1b3e07456342ec2d4e1 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 26 Mar 2021 17:57:50 +0100 Subject: [PATCH 023/185] not reading .raw files in SA --- executables/nr-ue.c | 29 +++++++++++++------------- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 7 ++++--- openair2/RRC/NR_UE/rrc_UE.c | 5 +++-- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index f175ab4980..5c1f931ebb 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -732,20 +732,21 @@ void init_NR_UE(int nb_inst, char* rrc_config_path) { AssertFatal((mac_inst = nr_l2_init_ue(rrc_inst)) != NULL, "can not initialize L2 module\n"); AssertFatal((mac_inst->if_module = nr_ue_if_module_init(inst)) != NULL, "can not initialize IF module\n"); - NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL; - if (mac_inst->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList) { - pusch_TimeDomainAllocationList = mac_inst->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList->choice.setup; - } - else if (mac_inst->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) { - pusch_TimeDomainAllocationList = mac_inst->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - } - - if (pusch_TimeDomainAllocationList) { - for(int i = 0; i < pusch_TimeDomainAllocationList->list.count; i++) { - AssertFatal(*pusch_TimeDomainAllocationList->list.array[i]->k2 >= DURATION_RX_TO_TX, - "Slot offset K2 (%ld) cannot be less than DURATION_RX_TO_TX (%d)\n", - *pusch_TimeDomainAllocationList->list.array[i]->k2, - DURATION_RX_TO_TX); + if(get_softmodem_params()->sa == 0) { + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL; + if (mac_inst->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = mac_inst->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList->choice.setup; + } + else if (mac_inst->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = mac_inst->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + } + if (pusch_TimeDomainAllocationList) { + for(int i = 0; i < pusch_TimeDomainAllocationList->list.count; i++) { + AssertFatal(*pusch_TimeDomainAllocationList->list.array[i]->k2 >= DURATION_RX_TO_TX, + "Slot offset K2 (%ld) cannot be less than DURATION_RX_TO_TX (%d)\n", + *pusch_TimeDomainAllocationList->list.array[i]->k2, + DURATION_RX_TO_TX); + } } } } diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index bbb44ba47a..c991e74739 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -42,8 +42,8 @@ static NR_UE_MAC_INST_t *nr_ue_mac_inst; -NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) -{ +NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { + //LOG_I(MAC, "[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n"); //LOG_I(MAC, "[MAIN] init UE MAC functions \n"); @@ -55,7 +55,8 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) if (IS_SOFTMODEM_NOS1){ AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); pdcp_layer_init(); - nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); + if(get_softmodem_params()->sa == 0) //TODO this needs to be done in SA after knowing the crnti + nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); } // Allocate memory for ul_config_request in the mac instance. This is now a pointer and will diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index f373d74230..312293abdc 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -481,7 +481,7 @@ NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char* rrc_config_path){ RRC_LIST_INIT(NR_UE_rrc_inst[nr_ue].CSI_ReportConfig_list, NR_maxNrofCSI_ReportConfigurations); } - if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra==1 || get_softmodem_params()->sa == 1) { + if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra==1) { // read in files for RRCReconfiguration and RBconfig FILE *fd; char filename[1024]; @@ -513,7 +513,8 @@ NR_UE_RRC_INST_t* openair_rrc_top_init_ue_nr(char* rrc_config_path){ fclose(fd); process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, buffer,msg_len); } - }else{ + } + else{ NR_UE_rrc_inst = NULL; } From 3de0730034e60aa999b6d92415181e11117fd3bb Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 26 Mar 2021 19:10:22 +0100 Subject: [PATCH 024/185] reuse softmodem common tags for command line paremeters --- executables/nr-softmodem-common.h | 1 - executables/nr-uesoftmodem.c | 15 +++++++++++---- executables/nr-uesoftmodem.h | 3 --- executables/softmodem-common.h | 12 ++++++------ openair1/PHY/INIT/nr_parms.c | 7 ++++--- openair1/PHY/INIT/phy_init.h | 2 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 3 +++ openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 10 +++++----- 8 files changed, 30 insertions(+), 23 deletions(-) diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index deb74294d7..a1e1c103ee 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -73,7 +73,6 @@ #define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" #define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" -#define CONFIG_HLP_MUSSB "Set the SSB SCS for UE SA\n" #define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" #define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" #define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n" diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 0ef6f1a785..29141f16b0 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -33,6 +33,7 @@ //#include "common/utils/threadPool/thread-pool.h" #include "common/utils/load_module_shlib.h" //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all +#include "common/utils/nr/nr_common.h" #include "../../ARCH/COMMON/common_lib.h" #include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" @@ -431,17 +432,23 @@ int main( int argc, char **argv ) { for (int CC_id=0; CC_idsa) - nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms,downlink_frequency[CC_id][0],uplink_frequency_offset[CC_id][0]); + if (get_softmodem_params()->sa) { + uint16_t nr_band = get_band(downlink_frequency[CC_id][0],uplink_frequency_offset[CC_id][0]); + mac->nr_band = nr_band; + nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms, + downlink_frequency[CC_id][0], + uplink_frequency_offset[CC_id][0], + get_softmodem_params()->numerology, + nr_band); + } else{ - NR_UE_MAC_INST_t *mac = get_mac_inst(0); if(mac->if_module != NULL && mac->if_module->phy_config_request != NULL) mac->if_module->phy_config_request(&mac->phy_config); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 42c2774729..37626fc549 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -56,10 +56,7 @@ {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&(UE->UE_fo_compensation), defintval:0, TYPE_INT, 0}, \ {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ - {"D" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF,TYPE_UINT64,0}, \ - {"U" , CONFIG_HLP_ULOFF, 0, iptr:&(uplink_frequency_offset[0][0]), defuintval:0, TYPE_INT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ - {"m" , CONFIG_HLP_MUSSB, 0, u8ptr:&(fp->numerology_index), defintval:0, TYPE_UINT8, 0}, \ {"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:106, TYPE_UINT, 0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 7a7be1de96..a5305ee6bd 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -123,14 +123,14 @@ extern "C" {"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \ {"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, iptr:&DO_RA, defintval:0, TYPE_INT, 0}, \ - {"sa", CONFIG_HLP_SA, PARAMFLAG_BOOL, iptr:&SA, defintval:0, TYPE_INT, 0}, \ + {"sa", CONFIG_HLP_SA, PARAMFLAG_BOOL, iptr:&SA, defintval:0, TYPE_INT, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \ - {"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ - {"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \ + {"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ + {"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \ {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \ {"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \ - {"CO" , CONFIG_HLP_ULF, 0, iptr:&(uplink_frequency_offset[0][0]), defintval:0, TYPE_INT, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \ + {"CO" , CONFIG_HLP_ULF, 0, iptr:&(uplink_frequency_offset[0][0]), defintval:0, TYPE_INT, 0}, \ {"a" , CONFIG_HLP_CHOFF, 0, iptr:&CHAIN_OFFSET, defintval:0, TYPE_INT, 0}, \ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ @@ -144,7 +144,7 @@ extern "C" {"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \ {"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \ - {"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \ + {"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \ } diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 1066ce3847..0d2a4d4770 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -327,20 +327,21 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, return 0; } -void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t delta_duplex) { +void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t delta_duplex, uint8_t mu, uint16_t nr_band) { LOG_I(PHY,"SA init parameters. DL freq %lu UL offset %d SSB numerology %d N_RB_DL %d\n", downlink_frequency, delta_duplex, - frame_parms->numerology_index, + mu, frame_parms->N_RB_DL); + frame_parms->numerology_index = mu; frame_parms->dl_CarrierFreq = downlink_frequency; frame_parms->ul_CarrierFreq = downlink_frequency + delta_duplex; frame_parms->freq_range = (frame_parms->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; frame_parms->N_RB_UL = frame_parms->N_RB_DL; - frame_parms->nr_band = get_band(downlink_frequency, delta_duplex); + frame_parms->nr_band = nr_band; frame_parms->frame_type = get_frame_type(frame_parms->nr_band, frame_parms->numerology_index); frame_parms->Ncp = NORMAL; diff --git a/openair1/PHY/INIT/phy_init.h b/openair1/PHY/INIT/phy_init.h index 01e4e583e5..e80f404762 100644 --- a/openair1/PHY/INIT/phy_init.h +++ b/openair1/PHY/INIT/phy_init.h @@ -394,7 +394,7 @@ void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms); int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb); int nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms); int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band); -void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset); +void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band); int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB,uint8_t abstraction_flag); void init_nr_ue_transport(PHY_VARS_NR_UE *ue,int abstraction_flag); void init_N_TA_offset(PHY_VARS_NR_UE *ue); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 933286f95a..a7a010999d 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -352,6 +352,7 @@ typedef struct { RA_config_t ra; /// SSB index from MIB decoding uint8_t mib_ssb; + /// Last NDI of UL HARQ processes uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES]; @@ -374,6 +375,8 @@ typedef struct { NR_SearchSpace_t *search_space_zero; NR_ControlResourceSet_t *coreset0; + uint16_t nr_band; + } NR_UE_MAC_INST_t; typedef enum seach_space_mask_e { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 91b2dc509b..33273f9984 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -105,7 +105,6 @@ int8_t nr_ue_decode_mib(module_id_t module_id, LOG_I(MAC,"[L2][MAC] decode mib\n"); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - NR_ServingCellConfigCommon_t *scc = mac->scc; frequency_range_t frequency_range; nr_mac_rrc_data_ind_ue( module_id, cc_id, gNB_index, NR_BCCH_BCH, (uint8_t *) pduP, 3 ); // fixed 3 bytes MIB PDU @@ -147,9 +146,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, if (get_softmodem_params()->sa == 1) { - // TODO these values shouldn't be taken from SCC in SA - uint8_t scs_ssb = *scc->ssbSubcarrierSpacing; - uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + uint8_t scs_ssb = get_softmodem_params()->numerology; + uint32_t band = mac->nr_band; uint16_t ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; @@ -170,9 +168,11 @@ int8_t nr_ue_decode_mib(module_id_t module_id, mac->type0_pdcch_ss_n_c = mac->type0_PDCCH_CSS_config.n_c; } - mac->dl_config_request.sfn = mac->type0_PDCCH_CSS_config.frame; + //TODO is this needed? + mac->dl_config_request.sfn = frame; mac->dl_config_request.slot = (ssb_index>>1) + ((ssb_index>>4)<<1); // not valid for 240kHz SCS + return 0; } From b711517a57fa3f2a98c6aceaeb3bfd54b9760bc5 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 29 Mar 2021 17:45:04 +0200 Subject: [PATCH 025/185] improved slot computation in decode mib function --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 21 +++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 33273f9984..327c95bb56 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -144,11 +144,14 @@ int8_t nr_ue_decode_mib(module_id_t module_id, //storing ssb index in the mac structure mac->mib_ssb = ssb_index; - if (get_softmodem_params()->sa == 1) { + uint8_t scs_ssb; + uint32_t band; + uint16_t ssb_start_symbol; - uint8_t scs_ssb = get_softmodem_params()->numerology; - uint32_t band = mac->nr_band; - uint16_t ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); + if (get_softmodem_params()->sa == 1) { + scs_ssb = get_softmodem_params()->numerology; + band = mac->nr_band; + ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; get_type0_PDCCH_CSS_config_parameters(&mac->type0_PDCCH_CSS_config, @@ -167,11 +170,15 @@ int8_t nr_ue_decode_mib(module_id_t module_id, mac->type0_pdcch_ss_sfn_c = mac->type0_PDCCH_CSS_config.sfn_c; mac->type0_pdcch_ss_n_c = mac->type0_PDCCH_CSS_config.n_c; } + else { + NR_ServingCellConfigCommon_t *scc = mac->scc; + scs_ssb = *scc->ssbSubcarrierSpacing; + band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); + } - //TODO is this needed? mac->dl_config_request.sfn = frame; - mac->dl_config_request.slot = (ssb_index>>1) + ((ssb_index>>4)<<1); // not valid for 240kHz SCS - + mac->dl_config_request.slot = ssb_start_symbol/14; return 0; } From 3aebb081309104181c88f79de423d654f103f79a Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 30 Mar 2021 17:34:33 +0200 Subject: [PATCH 026/185] function to schedule reception of sib1 --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 3 ++ openair2/LAYER2/NR_MAC_UE/mac_proto.h | 8 ++++ openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 24 ++++------ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 48 ++++++++++++++++++-- 4 files changed, 63 insertions(+), 20 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index a7a010999d..dcf387bc43 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -353,6 +353,9 @@ typedef struct { /// SSB index from MIB decoding uint8_t mib_ssb; + /// Flag for SIB1 + uint8_t sib1_received; + /// Last NDI of UL HARQ processes uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES]; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 44df0c54e1..685a01b5ab 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -231,6 +231,14 @@ void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac, sub_frame_t current_slot, uint8_t Msg3_tda_id); +void nr_ue_sib1_scheduler(module_id_t module_idP, + uint16_t ssb_start_symbol, + uint16_t frame, + uint8_t ssb_subcarrier_offset, + uint32_t ssb_index, + uint16_t ssb_start_subcarrier, + frequency_range_t frequency_range); + /* \brief Function called by PHY to process the received RAR and check that the preamble matches what was sent by the gNB. It provides the timing advance and t-CRNTI. @param Mod_id Index of UE instance @param CC_id Index to a component carrier diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 327c95bb56..aecab03b81 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -148,27 +148,19 @@ int8_t nr_ue_decode_mib(module_id_t module_id, uint32_t band; uint16_t ssb_start_symbol; - if (get_softmodem_params()->sa == 1) { + if ((get_softmodem_params()->sa == 1) && (mac->sib1_received == 0)) { scs_ssb = get_softmodem_params()->numerology; band = mac->nr_band; ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); - uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; - get_type0_PDCCH_CSS_config_parameters(&mac->type0_PDCCH_CSS_config, - frame, - mac->mib, - nr_slots_per_frame[scs_ssb], - ssb_subcarrier_offset, - ssb_start_symbol, - scs_ssb, - frequency_range, - ssb_index, - ssb_offset_point_a); + nr_ue_sib1_scheduler(module_id, + ssb_start_symbol, + frame, + ssb_subcarrier_offset, + ssb_index, + ssb_start_subcarrier, + frequency_range); - - mac->type0_pdcch_ss_mux_pattern = mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern; - mac->type0_pdcch_ss_sfn_c = mac->type0_PDCCH_CSS_config.sfn_c; - mac->type0_pdcch_ss_n_c = mac->type0_PDCCH_CSS_config.n_c; } else { NR_ServingCellConfigCommon_t *scc = mac->scc; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 0b58ea4041..39e3691557 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1439,7 +1439,9 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); - LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", + ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, + prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); // If all the required SSBs are mapped to this RO, exit the loop of SSBs @@ -1508,11 +1510,15 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { ro_p->nb_mapped_ssb = 1; ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; - AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); nb_mapped_ro_in_association_period++; - LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); - LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); + LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", + ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, + prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); // Exit the loop if this SSB has been mapped to all the required ROs // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period: @@ -1655,6 +1661,7 @@ void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){ LOG_D(MAC,"Map SSB to RO done\n"); } + // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. // - todo: @@ -1792,6 +1799,39 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s } // if is_nr_UL_slot } + +// This function schedules the reception of SIB1 after initial sync and before going to real time state +void nr_ue_sib1_scheduler(module_id_t module_idP, + uint16_t ssb_start_symbol, + uint16_t frame, + uint8_t ssb_subcarrier_offset, + uint32_t ssb_index, + uint16_t ssb_start_subcarrier, + frequency_range_t frequency_range) { + + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + + uint8_t scs_ssb = get_softmodem_params()->numerology; + uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; + + get_type0_PDCCH_CSS_config_parameters(&mac->type0_PDCCH_CSS_config, + frame, + mac->mib, + nr_slots_per_frame[scs_ssb], + ssb_subcarrier_offset, + ssb_start_symbol, + scs_ssb, + frequency_range, + ssb_index, + ssb_offset_point_a); + + mac->type0_pdcch_ss_mux_pattern = mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern; + mac->type0_pdcch_ss_sfn_c = mac->type0_PDCCH_CSS_config.sfn_c; + mac->type0_pdcch_ss_n_c = mac->type0_PDCCH_CSS_config.n_c; + +} + + uint8_t nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframe, uint8_t eNB_index, From 259191df0687297414f2fdf0c15b2614d9d460d1 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 2 Apr 2021 16:09:33 +0200 Subject: [PATCH 027/185] new functions to fill ss0 and coreset0 --- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 1 + openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 177 ++++++++++++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 4 + openair2/LAYER2/NR_MAC_UE/config_ue.c | 60 ------ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 86 +-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 7 +- openair2/RRC/NR/nr_rrc_proto.h | 4 - openair2/RRC/NR/rrc_gNB_reconfig.c | 68 ------- 8 files changed, 194 insertions(+), 213 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 67cf5051ef..43e2d29b97 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -452,6 +452,7 @@ typedef struct Type0_PDCCH_CSS_config_s { uint32_t number_of_search_space_per_slot; uint32_t first_symbol_index; uint32_t search_space_duration; + uint32_t search_space_frame_period; // in slots uint32_t ssb_length; uint32_t ssb_index; uint32_t cset_start_rb; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index c0b7e23c20..71db023fcd 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1075,6 +1075,79 @@ void find_aggregation_candidates(uint8_t *aggregation_level, *aggregation_level = 16; *nr_of_candidates = ss->nrofCandidates->aggregationLevel16; } + // n8 does not correspont to a value of 8 but 7, the following corrects this + if(*nr_of_candidates == 7) + *nr_of_candidates = 8; +} + + +void set_monitoring_periodicity_offset(NR_SearchSpace_t *ss, + uint16_t period, + uint16_t offset) { + + switch(period) { + case 1: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; + break; + case 2: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2; + ss->monitoringSlotPeriodicityAndOffset->choice.sl2 = offset; + break; + case 4: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl4; + ss->monitoringSlotPeriodicityAndOffset->choice.sl4 = offset; + break; + case 5: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5; + ss->monitoringSlotPeriodicityAndOffset->choice.sl5 = offset; + break; + case 8: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl8; + ss->monitoringSlotPeriodicityAndOffset->choice.sl8 = offset; + break; + case 10: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl10; + ss->monitoringSlotPeriodicityAndOffset->choice.sl10 = offset; + break; + case 16: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl16; + ss->monitoringSlotPeriodicityAndOffset->choice.sl16 = offset; + break; + case 20: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl20; + ss->monitoringSlotPeriodicityAndOffset->choice.sl20 = offset; + break; + case 40: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl40; + ss->monitoringSlotPeriodicityAndOffset->choice.sl40 = offset; + break; + case 80: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl80; + ss->monitoringSlotPeriodicityAndOffset->choice.sl80 = offset; + break; + case 160: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl160; + ss->monitoringSlotPeriodicityAndOffset->choice.sl160 = offset; + break; + case 320: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl320; + ss->monitoringSlotPeriodicityAndOffset->choice.sl320 = offset; + break; + case 640: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl640; + ss->monitoringSlotPeriodicityAndOffset->choice.sl640 = offset; + break; + case 1280: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1280; + ss->monitoringSlotPeriodicityAndOffset->choice.sl1280 = offset; + break; + case 2560: + ss->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl2560; + ss->monitoringSlotPeriodicityAndOffset->choice.sl2560 = offset; break; + default: + AssertFatal(1==0,"Invalid monitoring slot periodicity value\n"); + break; + } } @@ -3043,6 +3116,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD NR_SubcarrierSpacing_t scs_ssb, frequency_range_t frequency_range, uint32_t ssb_index, + uint32_t ssb_period, uint32_t ssb_offset_point_a) { NR_SubcarrierSpacing_t scs_pdcch; @@ -3255,6 +3329,8 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD } // 38.213 chapter 13: over two consecutive slots type0_PDCCH_CSS_config->search_space_duration = 2; + // two frames + type0_PDCCH_CSS_config->search_space_frame_period = nr_slots_per_frame[scs_ssb]<<1; } if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){ @@ -3271,6 +3347,8 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD } // 38.213 chapter 13: over two consecutive slots type0_PDCCH_CSS_config->search_space_duration = 2; + // two frames + type0_PDCCH_CSS_config->search_space_frame_period = nr_slots_per_frame[scs_ssb]<<1; } /// MUX PATTERN 2 @@ -3336,6 +3414,8 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD }else{ ; } // 38.213 chapter 13: over one slot type0_PDCCH_CSS_config->search_space_duration = 1; + // SSB periodicity in slots + type0_PDCCH_CSS_config->search_space_frame_period = ssb_period*nr_slots_per_frame[scs_ssb]; } /// MUX PATTERN 3 @@ -3364,6 +3444,8 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD }else{ ; } // 38.213 chapter 13: over one slot type0_PDCCH_CSS_config->search_space_duration = 1; + // SSB periodicity in slots + type0_PDCCH_CSS_config->search_space_frame_period = ssb_period*nr_slots_per_frame[scs_ssb]; } AssertFatal(type0_PDCCH_CSS_config->number_of_search_space_per_slot!=UINT_MAX,""); @@ -3387,6 +3469,101 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD } + +void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { + + int32_t duration; + coreset0->controlResourceSetId = 0; + + AssertFatal(type0_PDCCH_CSS_config!=NULL,"No type0 CSS configuration\n"); + + duration = type0_PDCCH_CSS_config->num_symbols; + + // Not to be used for ControlResourceSetZero + coreset0->frequencyDomainResources.buf = NULL; + + coreset0->duration = duration; + coreset0->cce_REG_MappingType.present=NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved; + coreset0->cce_REG_MappingType.choice.interleaved=calloc(1,sizeof(*coreset0->cce_REG_MappingType.choice.interleaved)); + coreset0->cce_REG_MappingType.choice.interleaved->reg_BundleSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6; + coreset0->cce_REG_MappingType.choice.interleaved->interleaverSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n2; + coreset0->cce_REG_MappingType.choice.interleaved->shiftIndex = NULL; // -> use cell_id + coreset0->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; + + coreset0->tci_StatesPDCCH_ToAddList = NULL; + coreset0->tci_StatesPDCCH_ToReleaseList = NULL; + coreset0->tci_PresentInDCI = NULL; + coreset0->pdcch_DMRS_ScramblingID = NULL; + +} + +void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { + + if(ss0->controlResourceSetId == NULL) ss0->controlResourceSetId=calloc(1,sizeof(*ss0->controlResourceSetId)); + if(ss0->monitoringSymbolsWithinSlot == NULL) ss0->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss0->monitoringSymbolsWithinSlot)); + if(ss0->monitoringSymbolsWithinSlot->buf == NULL) ss0->monitoringSymbolsWithinSlot->buf = calloc(1,2); + if(ss0->nrofCandidates == NULL) ss0->nrofCandidates = calloc(1,sizeof(*ss0->nrofCandidates)); + if(ss0->searchSpaceType == NULL) ss0->searchSpaceType = calloc(1,sizeof(*ss0->searchSpaceType)); + if(ss0->searchSpaceType->choice.common == NULL) ss0->searchSpaceType->choice.common=calloc(1,sizeof(*ss0->searchSpaceType->choice.common)); + if(ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 == NULL) + ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); + + uint32_t duration,periodicity,offset; + uint16_t symbols,n_cces; + + AssertFatal(type0_PDCCH_CSS_config!=NULL,"No type0 CSS configuration\n"); + + n_cces = (type0_PDCCH_CSS_config->num_symbols*type0_PDCCH_CSS_config->num_rbs)/6; + symbols = (1-(1<num_symbols))<first_symbol_index; + duration = type0_PDCCH_CSS_config->search_space_duration; + periodicity = type0_PDCCH_CSS_config->search_space_frame_period; + if (type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1) + offset = type0_PDCCH_CSS_config->n_0; + else + offset = type0_PDCCH_CSS_config->n_c; + + ss0->searchSpaceId = 0; + *ss0->controlResourceSetId = 0; + ss0->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss0->monitoringSlotPeriodicityAndOffset)); + set_monitoring_periodicity_offset(ss0,periodicity,offset); + if (duration==1) + ss0->duration = NULL; + else{ + ss0->duration = calloc(1,sizeof(*ss0->duration)); + *ss0->duration = duration; + } + + ss0->monitoringSymbolsWithinSlot->size = 2; + ss0->monitoringSymbolsWithinSlot->bits_unused = 2; + ss0->monitoringSymbolsWithinSlot->buf[1] = 0; + ss0->monitoringSymbolsWithinSlot->buf[0] = 0; + for (int i=0; i<8; i++) { + ss0->monitoringSymbolsWithinSlot->buf[1] |= ((symbols>>(i+8))&0x01)<<(7-i); + ss0->monitoringSymbolsWithinSlot->buf[0] |= ((symbols>>i)&0x01)<<(7-i); + } + + // values according to TS38.213 Section 10.1 Table 10.1-1 + ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + switch(n_cces){ + case 4: + ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; + break; + case 8: + ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n2; + break; + case 16: + ss0->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n1; + break; + default: + AssertFatal(1==0,"Invalid number of CCEs %d for SS0\n",n_cces); + } + + ss0->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; +} + + + /* extract UL PTRS values from RRC and validate it based upon 38.214 6.2.3 */ bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 741b4e4799..2723b85efb 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -135,10 +135,14 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD NR_SubcarrierSpacing_t scs_ssb, frequency_range_t frequency_range, uint32_t ssb_index, + uint32_t ssb_period, uint32_t ssb_offset_point_a); uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i_ssb); +void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); +void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); + int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index fee2efc4a8..47b0908d3f 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -442,66 +442,6 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ ss_id++; } - // TODO: Merge this code in a single function as fill_default_searchSpaceZero() in rrc_gNB_reconfig.c - // Search space zero - if(mac->search_space_zero == NULL) mac->search_space_zero=calloc(1,sizeof(*mac->search_space_zero)); - if(mac->search_space_zero->controlResourceSetId == NULL) mac->search_space_zero->controlResourceSetId=calloc(1,sizeof(*mac->search_space_zero->controlResourceSetId)); - if(mac->search_space_zero->monitoringSymbolsWithinSlot == NULL) mac->search_space_zero->monitoringSymbolsWithinSlot = calloc(1,sizeof(*mac->search_space_zero->monitoringSymbolsWithinSlot)); - if(mac->search_space_zero->monitoringSymbolsWithinSlot->buf == NULL) mac->search_space_zero->monitoringSymbolsWithinSlot->buf = calloc(1,2); - if(mac->search_space_zero->nrofCandidates == NULL) mac->search_space_zero->nrofCandidates = calloc(1,sizeof(*mac->search_space_zero->nrofCandidates)); - if(mac->search_space_zero->searchSpaceType == NULL) mac->search_space_zero->searchSpaceType = calloc(1,sizeof(*mac->search_space_zero->searchSpaceType)); - if(mac->search_space_zero->searchSpaceType->choice.common == NULL) mac->search_space_zero->searchSpaceType->choice.common=calloc(1,sizeof(*mac->search_space_zero->searchSpaceType->choice.common)); - if(mac->search_space_zero->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 == NULL) mac->search_space_zero->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*mac->search_space_zero->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); - mac->search_space_zero->searchSpaceId = 0; - *mac->search_space_zero->controlResourceSetId = 0; - mac->search_space_zero->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*mac->search_space_zero->monitoringSlotPeriodicityAndOffset)); - mac->search_space_zero->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; - mac->search_space_zero->duration=NULL; - // should be '1100 0000 0000 00'B (LSB first!), first two symbols in slot, adjust if needed - mac->search_space_zero->monitoringSymbolsWithinSlot->buf[1] = 0; - mac->search_space_zero->monitoringSymbolsWithinSlot->buf[0] = (1<<7); - mac->search_space_zero->monitoringSymbolsWithinSlot->size = 2; - mac->search_space_zero->monitoringSymbolsWithinSlot->bits_unused = 2; - - // FIXME: update values from TS38.213 Section 10.1 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE aggregation level for CSS sets configured by searchSpaceSIB1 - mac->search_space_zero->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; - mac->search_space_zero->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - mac->search_space_zero->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; - mac->search_space_zero->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; - mac->search_space_zero->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; - mac->search_space_zero->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; - - // Coreset0 - if(mac->coreset0 == NULL) mac->coreset0 = calloc(1,sizeof(*mac->coreset0)); - mac->coreset0->controlResourceSetId = 0; - // frequencyDomainResources '11111111 00000000 00000000 00000000 00000000 00000'B, - if(mac->coreset0->frequencyDomainResources.buf == NULL) mac->coreset0->frequencyDomainResources.buf = calloc(1,6); - mac->coreset0->frequencyDomainResources.buf[0] = 0xff; - mac->coreset0->frequencyDomainResources.buf[1] = 0; - mac->coreset0->frequencyDomainResources.buf[2] = 0; - mac->coreset0->frequencyDomainResources.buf[3] = 0; - mac->coreset0->frequencyDomainResources.buf[4] = 0; - mac->coreset0->frequencyDomainResources.buf[5] = 0; - mac->coreset0->frequencyDomainResources.size = 6; - mac->coreset0->frequencyDomainResources.bits_unused = 3; - mac->coreset0->duration = 1; - mac->coreset0->cce_REG_MappingType.present=NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved; - mac->coreset0->cce_REG_MappingType.choice.interleaved=calloc(1,sizeof(*mac->coreset0->cce_REG_MappingType.choice.interleaved)); - mac->coreset0->cce_REG_MappingType.choice.interleaved->reg_BundleSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6; - mac->coreset0->cce_REG_MappingType.choice.interleaved->interleaverSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n2; - mac->coreset0->cce_REG_MappingType.choice.interleaved->shiftIndex = NULL; - mac->coreset0->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; - if(mac->coreset0->tci_StatesPDCCH_ToAddList == NULL) mac->coreset0->tci_StatesPDCCH_ToAddList = calloc(1,sizeof(*mac->coreset0->tci_StatesPDCCH_ToAddList)); - NR_TCI_StateId_t *tci[8]; - for (int i=0;i<8;i++) { - tci[i]=calloc(1,sizeof(*tci[i])); - *tci[i] = i; - ASN_SEQUENCE_ADD(&mac->coreset0->tci_StatesPDCCH_ToAddList->list,tci[i]); - } - mac->coreset0->tci_StatesPDCCH_ToReleaseList = NULL; - mac->coreset0->tci_PresentInDCI = NULL; - mac->coreset0->pdcch_DMRS_ScramblingID = NULL; - } int nr_rrc_mac_config_req_ue( diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 39e3691557..2505df2165 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -771,8 +771,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, // 3. TODO: Perform PHR procedures NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_indication_t *ul_info){ - uint32_t search_space_mask = 0; - if (dl_info){ module_id_t mod_id = dl_info->module_id; @@ -782,65 +780,10 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in slot_t rx_slot = dl_info->slot; NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; nr_scheduled_response_t scheduled_response; nr_dcireq_t dcireq; - // check type0 from 38.213 13 if we have no CellGroupConfig - // TODO: implementation to be completed - if (mac->scg == NULL) { - - if(dl_info->ssb_index != -1){ - - if(mac->type0_pdcch_ss_mux_pattern == 1){ - // 38.213 chapter 13 - if((mac->type0_pdcch_ss_sfn_c == SFN_C_MOD_2_EQ_0) && !(rx_frame & 0x1) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - if((mac->type0_pdcch_ss_sfn_c == SFN_C_MOD_2_EQ_1) && (rx_frame & 0x1) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - if(mac->type0_pdcch_ss_mux_pattern == 2){ - // 38.213 Table 13-13, 13-14 - if((rx_frame == get_ssb_frame(rx_frame)) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - if(mac->type0_pdcch_ss_mux_pattern == 3){ - // 38.213 Table 13-15 - if((rx_frame == get_ssb_frame(rx_frame)) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - } // ssb_index != -1 - - // Type0 PDCCH search space - if((search_space_mask & type0_pdcch) || ( mac->type0_pdcch_consecutive_slots != 0 )){ - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_consecutive_slots - 1; - - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15 = mac->type0_pdcch_dci_config; - dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - - /* - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.rnti = 0xaaaa; // to be set - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = 106; // to be set - - LOG_I(MAC,"nr_ue_scheduler Type0 PDCCH with rnti %x, BWP %d\n", - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.rnti, - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP); - */ - dl_config->number_pdus = dl_config->number_pdus + 1; - - fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) - mac->if_module->scheduled_response(&scheduled_response); - } - } else { // we have an scg + if(mac->scg != NULL){ // we have an scg dcireq.module_id = mod_id; dcireq.gNB_index = gNB_index; @@ -854,20 +797,6 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ mac->if_module->scheduled_response(&scheduled_response); } - - /* - if(search_space_mask & type0a_pdcch){ - } - - if(search_space_mask & type1_pdcch){ - } - - if(search_space_mask & type2_pdcch){ - } - - if(search_space_mask & type3_pdcch){ - } - */ } } else if (ul_info) { @@ -1823,19 +1752,18 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, scs_ssb, frequency_range, ssb_index, + 1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame ssb_offset_point_a); - mac->type0_pdcch_ss_mux_pattern = mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern; - mac->type0_pdcch_ss_sfn_c = mac->type0_PDCCH_CSS_config.sfn_c; - mac->type0_pdcch_ss_n_c = mac->type0_PDCCH_CSS_config.n_c; + fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); + fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config); } -uint8_t -nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, - sub_frame_t subframe, uint8_t eNB_index, - uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) { +uint8_t nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) { uint8_t total_rlc_pdu_header_len = 0; int16_t buflen_remain = 0; uint8_t lcid = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index a82d7e4549..c37cb16e78 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -211,6 +211,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, scs, FR1, i_ssb, + ssb_frame_periodicity, offset_pointa); gNB->type0_PDCCH_CSS_config[i_ssb].active = true; } @@ -237,6 +238,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, scs, FR1, i_ssb, + ssb_frame_periodicity, offset_pointa); gNB->type0_PDCCH_CSS_config[i_ssb].active = true; } @@ -263,6 +265,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, scs, FR2, i_ssb, + ssb_frame_periodicity, offset_pointa); gNB->type0_PDCCH_CSS_config[i_ssb].active = true; } @@ -315,8 +318,8 @@ void schedule_control_sib1(module_id_t module_id, gNB_mac->sched_ctrlCommon->search_space = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->search_space)); gNB_mac->sched_ctrlCommon->coreset = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->coreset)); gNB_mac->sched_ctrlCommon->active_bwp = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->active_bwp)); - fill_default_searchSpaceZero(gNB_mac->sched_ctrlCommon->search_space); - fill_default_coresetZero(gNB_mac->sched_ctrlCommon->coreset,servingcellconfigcommon); + fill_searchSpaceZero(gNB_mac->sched_ctrlCommon->search_space,type0_PDCCH_CSS_config); + fill_coresetZero(gNB_mac->sched_ctrlCommon->coreset,type0_PDCCH_CSS_config); fill_default_initialDownlinkBWP(gNB_mac->sched_ctrlCommon->active_bwp,servingcellconfigcommon); } gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 5aafbaee4c..69b8481286 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -74,10 +74,6 @@ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); void fill_default_initialDownlinkBWP(NR_BWP_Downlink_t *bwp, NR_ServingCellConfigCommon_t *servingcellconfigcommon); -void fill_default_coresetZero(NR_ControlResourceSet_t *coreset0, NR_ServingCellConfigCommon_t *servingcellconfigcommon); - -void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0); - void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_ServingCellConfig_t *servingcellconfigdedicated, NR_CellGroupConfig_t *secondaryCellGroup, diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 8f3993229e..ec3fc5c5bd 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -75,74 +75,6 @@ void fill_default_initialDownlinkBWP(NR_BWP_Downlink_t *bwp, NR_ServingCellConfi *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0; } -void fill_default_coresetZero(NR_ControlResourceSet_t *coreset0, NR_ServingCellConfigCommon_t *servingcellconfigcommon) { - - coreset0->controlResourceSetId = 0; - - // frequencyDomainResources '11111111 00000000 00000000 00000000 00000000 00000'B, - if(coreset0->frequencyDomainResources.buf == NULL) coreset0->frequencyDomainResources.buf = calloc(1,6); - coreset0->frequencyDomainResources.buf[0] = 0xff; - coreset0->frequencyDomainResources.buf[1] = 0; - coreset0->frequencyDomainResources.buf[2] = 0; - coreset0->frequencyDomainResources.buf[3] = 0; - coreset0->frequencyDomainResources.buf[4] = 0; - coreset0->frequencyDomainResources.buf[5] = 0; - coreset0->frequencyDomainResources.size = 6; - coreset0->frequencyDomainResources.bits_unused = 3; - coreset0->duration = 1; - coreset0->cce_REG_MappingType.present=NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved; - coreset0->cce_REG_MappingType.choice.interleaved=calloc(1,sizeof(*coreset0->cce_REG_MappingType.choice.interleaved)); - coreset0->cce_REG_MappingType.choice.interleaved->reg_BundleSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6; - coreset0->cce_REG_MappingType.choice.interleaved->interleaverSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n2; - coreset0->cce_REG_MappingType.choice.interleaved->shiftIndex = servingcellconfigcommon->physCellId; - coreset0->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; - - if(coreset0->tci_StatesPDCCH_ToAddList == NULL) coreset0->tci_StatesPDCCH_ToAddList = calloc(1,sizeof(*coreset0->tci_StatesPDCCH_ToAddList)); - - NR_TCI_StateId_t *tci[8]; - for (int i=0;i<8;i++) { - tci[i]=calloc(1,sizeof(*tci[i])); - *tci[i] = i; - ASN_SEQUENCE_ADD(&coreset0->tci_StatesPDCCH_ToAddList->list,tci[i]); - } - coreset0->tci_StatesPDCCH_ToReleaseList = NULL; - coreset0->tci_PresentInDCI = NULL; - coreset0->pdcch_DMRS_ScramblingID = NULL; - -} - -void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) { - - if(ss0->controlResourceSetId == NULL) ss0->controlResourceSetId=calloc(1,sizeof(*ss0->controlResourceSetId)); - if(ss0->monitoringSymbolsWithinSlot == NULL) ss0->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss0->monitoringSymbolsWithinSlot)); - if(ss0->monitoringSymbolsWithinSlot->buf == NULL) ss0->monitoringSymbolsWithinSlot->buf = calloc(1,2); - if(ss0->nrofCandidates == NULL) ss0->nrofCandidates = calloc(1,sizeof(*ss0->nrofCandidates)); - if(ss0->searchSpaceType == NULL) ss0->searchSpaceType = calloc(1,sizeof(*ss0->searchSpaceType)); - if(ss0->searchSpaceType->choice.common == NULL) ss0->searchSpaceType->choice.common=calloc(1,sizeof(*ss0->searchSpaceType->choice.common)); - if(ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 == NULL) ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); - - ss0->searchSpaceId = 0; - *ss0->controlResourceSetId = 0; - ss0->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss0->monitoringSlotPeriodicityAndOffset)); - ss0->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; - ss0->duration=NULL; - - // should be '1100 0000 0000 00'B (LSB first!), first two symols in slot, adjust if needed - ss0->monitoringSymbolsWithinSlot->buf[1] = 0; - ss0->monitoringSymbolsWithinSlot->buf[0] = (1<<7); - ss0->monitoringSymbolsWithinSlot->size = 2; - ss0->monitoringSymbolsWithinSlot->bits_unused = 2; - - // FIXME: update values from TS38.213 Section 10.1 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE aggregation level for CSS sets configured by searchSpaceSIB1 - ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; - ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; - ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; - ss0->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; - - ss0->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; -} - void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_ServingCellConfig_t *servingcellconfigdedicated, NR_CellGroupConfig_t *secondaryCellGroup, From 438a6fe0fc55fbd95ef662378be6911df0531446 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 2 Apr 2021 18:20:30 +0200 Subject: [PATCH 028/185] fixes in fill ss0 and coreset0 --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 71db023fcd..88420c9f33 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3473,14 +3473,40 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { int32_t duration; + + if (coreset0 == NULL) + coreset0 = calloc(1,sizeof(*coreset0)); + coreset0->controlResourceSetId = 0; AssertFatal(type0_PDCCH_CSS_config!=NULL,"No type0 CSS configuration\n"); duration = type0_PDCCH_CSS_config->num_symbols; - // Not to be used for ControlResourceSetZero - coreset0->frequencyDomainResources.buf = NULL; + if(coreset0->frequencyDomainResources.buf == NULL) coreset0->frequencyDomainResources.buf = calloc(1,6); + + switch(type0_PDCCH_CSS_config->num_rbs){ + case 24: + coreset0->frequencyDomainResources.buf[0] = 0xf0; + coreset0->frequencyDomainResources.buf[1] = 0; + break; + case 48: + coreset0->frequencyDomainResources.buf[0] = 0xff; + coreset0->frequencyDomainResources.buf[1] = 0; + break; + case 96: + coreset0->frequencyDomainResources.buf[0] = 0xff; + coreset0->frequencyDomainResources.buf[1] = 0xff; + break; + default: + AssertFatal(1==0,"Invalid number of PRBs %d for Coreset0\n",type0_PDCCH_CSS_config->num_rbs); + } + coreset0->frequencyDomainResources.buf[2] = 0; + coreset0->frequencyDomainResources.buf[3] = 0; + coreset0->frequencyDomainResources.buf[4] = 0; + coreset0->frequencyDomainResources.buf[5] = 0; + coreset0->frequencyDomainResources.size = 6; + coreset0->frequencyDomainResources.bits_unused = 3; coreset0->duration = duration; coreset0->cce_REG_MappingType.present=NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved; @@ -3499,6 +3525,7 @@ void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_conf void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { + if(ss0 == NULL) ss0=calloc(1,sizeof(*ss0)); if(ss0->controlResourceSetId == NULL) ss0->controlResourceSetId=calloc(1,sizeof(*ss0->controlResourceSetId)); if(ss0->monitoringSymbolsWithinSlot == NULL) ss0->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss0->monitoringSymbolsWithinSlot)); if(ss0->monitoringSymbolsWithinSlot->buf == NULL) ss0->monitoringSymbolsWithinSlot->buf = calloc(1,2); From cb31468c16ba7566efd44b3031f922d7b4c82320 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 5 Apr 2021 10:15:22 +0200 Subject: [PATCH 029/185] first version of scheduler for sib1 --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 3 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 4 +++ .../NR_MAC_UE/nr_ue_dci_configuration.c | 33 ++++++++++--------- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 9 ++--- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 31 +++++++++++++++++ .../NR_MAC_gNB/gNB_scheduler_primitives.c | 3 -- 6 files changed, 59 insertions(+), 24 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index dcf387bc43..11d27b6a2e 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -311,6 +311,7 @@ typedef struct { NR_CellGroupConfig_t *scg; int servCellIndex; NR_CSI_ReportConfig_t *csirc; + long physCellId; //// MAC config NR_DRX_Config_t *drx_Config; NR_SchedulingRequestConfig_t *schedulingRequestConfig; @@ -377,7 +378,7 @@ typedef struct { NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config; NR_SearchSpace_t *search_space_zero; NR_ControlResourceSet_t *coreset0; - + frequency_range_t frequency_range; uint16_t nr_band; } NR_UE_MAC_INST_t; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 685a01b5ab..30d5b9eb41 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -232,6 +232,7 @@ void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac, uint8_t Msg3_tda_id); void nr_ue_sib1_scheduler(module_id_t module_idP, + int cc_id, uint16_t ssb_start_symbol, uint16_t frame, uint8_t ssb_subcarrier_offset, @@ -305,6 +306,9 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p uint16_t n_RB_DLBWP, uint16_t riv); +void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id); +void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); + void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu, uint8_t *nb_dmrs_re_per_rb, uint16_t *number_dmrs_symbols); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 11edc6c20d..c8e071c239 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -68,20 +68,22 @@ void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pd void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id){ - RA_config_t *ra = &mac->ra; uint16_t monitoringSymbolsWithinSlot = 0; uint8_t coreset_id = 1; int sps = 0; def_dci_pdu_rel15 = calloc(1,2*sizeof(dci_pdu_rel15_t)); - AssertFatal(mac->scc != NULL, "scc is null\n"); + NR_BWP_Id_t bwp_id = mac->DL_BWP_Id; NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_BWP_DownlinkCommon_t *bwp_Common = mac->DLbwp[bwp_id - 1]->bwp_Common; - NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; + NR_BWP_DownlinkCommon_t *bwp_Common = NULL; + NR_BWP_DownlinkCommon_t *initialDownlinkBWP = NULL; NR_SearchSpace_t *ss; NR_ControlResourceSet_t *coreset; if(ss_id>=0) { + AssertFatal(mac->scc != NULL, "scc is null\n"); + initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; + bwp_Common = mac->DLbwp[bwp_id - 1]->bwp_Common; ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id]; coreset = mac->coreset[bwp_id - 1][coreset_id - 1]; rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; @@ -100,8 +102,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved; rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize); rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize); - AssertFatal(scc->physCellId != NULL, "mac->scc->physCellId is null\n"); - rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : *scc->physCellId; + rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : mac->physCellId; } else { rel15->coreset.RegBundleSize = 0; rel15->coreset.InterleaverSize = 0; @@ -115,14 +116,10 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID; rel15->coreset.scrambling_rnti = mac->crnti; } else { - rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId; + rel15->coreset.pdcch_dmrs_scrambling_id = mac->physCellId; rel15->coreset.scrambling_rnti = 0; } - #ifdef DEBUG_DCI - LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: ss_id %d bwp %p bwp_Id %d controlResourceSetId %d\n", ss_id, mac->DLbwp[bwp_id - 1], mac->DLbwp[bwp_id - 1]->bwp_Id, coreset->controlResourceSetId); - #endif - // loop over RNTI type and configure resource allocation for DCI switch(rnti_type) { case NR_RNTI_C: @@ -142,7 +139,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t // we use the initial DL BWP sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12; monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - rel15->rnti = ra->ra_rnti; + rel15->rnti = mac->ra.ra_rnti; rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); //NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; @@ -157,8 +154,8 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t case NR_RNTI_SP_CSI: break; case NR_RNTI_SI: - // we use DL BWP dedicated - sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; + if (bwp_Common) sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; + else sps=14; // note: normally this would be found with SSS detection // for SPS=14 8 MSBs in positions 13 down to 6 monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); @@ -166,10 +163,14 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t rel15->rnti = SI_RNTI; // SI-RNTI - 3GPP TS 38.321 Table 7.1-1: RNTI values rel15->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs; rel15->BWPStart = mac->type0_PDCCH_CSS_config.cset_start_rb; - rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon; + + if(mac->frequency_range == FR1) + rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon; + else + rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2; for (int i = 0; i < rel15->num_dci_options; i++) { - rel15->dci_length_options[i] = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format_options[i], NR_RNTI_SI, rel15->BWPSize, 0); + rel15->dci_length_options[i] = nr_dci_size(NULL, NULL, def_dci_pdu_rel15, rel15->dci_format_options[i], NR_RNTI_SI, rel15->BWPSize, 0); } break; case NR_RNTI_SFI: diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index aecab03b81..6a1aaed15f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -105,7 +105,7 @@ int8_t nr_ue_decode_mib(module_id_t module_id, LOG_I(MAC,"[L2][MAC] decode mib\n"); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - frequency_range_t frequency_range; + mac->physCellId = cell_id; nr_mac_rrc_data_ind_ue( module_id, cc_id, gNB_index, NR_BCCH_BCH, (uint8_t *) pduP, 3 ); // fixed 3 bytes MIB PDU AssertFatal(mac->mib != NULL, "nr_ue_decode_mib() mac->mib == NULL\n"); @@ -121,11 +121,11 @@ int8_t nr_ue_decode_mib(module_id_t module_id, frame = frame << 4; frame = frame | frame_number_4lsb; if(ssb_length == 64){ - frequency_range = FR2; + mac->frequency_range = FR2; for (int i=0; i<3; i++) ssb_index += (((extra_bits>>(7-i))&0x01)<<(3+i)); }else{ - frequency_range = FR1; + mac->frequency_range = FR1; if(ssb_subcarrier_offset_msb){ ssb_subcarrier_offset = ssb_subcarrier_offset | 0x10; } @@ -154,12 +154,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id, ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); nr_ue_sib1_scheduler(module_id, + cc_id, ssb_start_symbol, frame, ssb_subcarrier_offset, ssb_index, ssb_start_subcarrier, - frequency_range); + mac->frequency_range); } else { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 2505df2165..31ebc9f92f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1731,6 +1731,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s // This function schedules the reception of SIB1 after initial sync and before going to real time state void nr_ue_sib1_scheduler(module_id_t module_idP, + int cc_id, uint16_t ssb_start_symbol, uint16_t frame, uint8_t ssb_subcarrier_offset, @@ -1739,6 +1740,8 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, frequency_range_t frequency_range) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + nr_scheduled_response_t scheduled_response; + int frame_s,slot_s; uint8_t scs_ssb = get_softmodem_params()->numerology; uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; @@ -1755,9 +1758,37 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, 1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame ssb_offset_point_a); + if(mac->search_space_zero == NULL) mac->search_space_zero=calloc(1,sizeof(*mac->search_space_zero)); + if(mac->coreset0 == NULL) mac->coreset0 = calloc(1,sizeof(*mac->coreset0)); + fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config); + fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); + fill_dci_search_candidates(mac->search_space_zero, rel15); + + if(mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern == 1){ + // same frame as ssb + if ((mac->type0_PDCCH_CSS_config.frame & 0x1) == mac->type0_PDCCH_CSS_config.sfn_c) + frame_s = 0; + else + frame_s = 1; + slot_s = mac->type0_PDCCH_CSS_config.n_0; + } + else{ + frame_s = 0; // same frame as ssb + slot_s = mac->type0_PDCCH_CSS_config.n_c; + } + + LOG_I(MAC,"Calling fill_scheduled_response, type0_pdcch, num_pdus %d\n",dl_config->number_pdus); + fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, module_idP, cc_id, frame_s, slot_s, 0); // TODO fix thread_id, for now assumed 0 + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); + } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 94524795f3..aa944f47b7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -171,9 +171,6 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac, uint16_t Y, int m, int nr_of_candidates) { - // uncomment these when we allocate for common search space - // NR_COMMON_channels_t *cc = nr_mac->common_channels; - // NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; int coreset_id = coreset->controlResourceSetId; From 83ad469a33c23a4da3395cd468ca5bcbf12f9405 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 5 Apr 2021 11:03:37 +0200 Subject: [PATCH 030/185] add option sa for sib1 detection in initial sync --- executables/nr-ue.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 6 +++++- openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h | 3 ++- openair1/SIMULATION/NR_PHY/pbchsim.c | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 5c1f931ebb..c6998b8e82 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -221,7 +221,7 @@ static void UE_synch(void *arg) { double rx_gain_off = 0; nr_get_carrier_frequencies(&UE->frame_parms, &dl_carrier, &ul_carrier); - if (nr_initial_sync(&syncD->proc, UE, 2) == 0) { + if (nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa) == 0) { freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) + round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index dbf957992e..f2a1a808d5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -202,7 +202,7 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini char duplex_string[2][4] = {"FDD","TDD"}; char prefix_string[2][9] = {"NORMAL","EXTENDED"}; -int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames) +int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa) { int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2, @@ -478,6 +478,10 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames) #endif #endif + } + // if stand alone and sync on ssb + if (sa==1 && ret==0) { + } // exit_fun("debug exit"); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 91274b908a..8604c79688 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1452,7 +1452,8 @@ void generate_RIV_tables(void); */ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, - int n_frames); + int n_frames, + int sa); /*! \brief This function gets the carrier frequencies either from FP or command-line-set global variables, depending on the availability of the latter diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index ee74909a9e..746138195e 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -682,7 +682,7 @@ int main(int argc, char **argv) } if (UE->is_synchronized == 0) { UE_nr_rxtx_proc_t proc={0}; - ret = nr_initial_sync(&proc, UE, 1); + ret = nr_initial_sync(&proc, UE, 1, 0); printf("nr_initial_sync1 returns %d\n",ret); if (ret<0) n_errors++; } From be6b413a82ee7bbfd08cd69850fca22e8e797576 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Thu, 17 Dec 2020 14:18:19 +0100 Subject: [PATCH 031/185] moving initialization of gold for pdcch to nr_init_ue --- openair1/PHY/INIT/nr_init_ue.c | 3 +++ openair1/PHY/NR_REFSIG/nr_gold_ue.c | 11 ++--------- openair1/PHY/NR_REFSIG/refsig_defs_ue.h | 3 +-- .../PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 7 +++++++ openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 1 - openair1/PHY/defs_nr_UE.h | 6 ++++++ openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 1 - 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 3132fb9960..5e13cb7a9e 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -291,6 +291,9 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, } } + ue->scramblingID_pdcch = fp->Nid_cell; + nr_gold_pdcch(ue,fp->Nid_cell); + //PDSCH DMRS init (eNB offset = 0) ue->nr_gold_pdsch[0] = (uint32_t ****)malloc16(fp->slots_per_frame*sizeof(uint32_t ***)); uint32_t ****pdsch_dmrs = ue->nr_gold_pdsch[0]; diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c index eefa6270ab..edb53a2272 100644 --- a/openair1/PHY/NR_REFSIG/nr_gold_ue.c +++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c @@ -52,22 +52,15 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue) } void nr_gold_pdcch(PHY_VARS_NR_UE* ue, - unsigned short n_idDMRS, - unsigned short length_dmrs) + unsigned short nid) { unsigned char ns,l; unsigned int n,x1,x2,x2tmp0; - unsigned int nid; uint8_t reset; - if (n_idDMRS) - nid = n_idDMRS; - else - nid = ue->frame_parms.Nid_cell; - for (ns=0; nsframe_parms.slots_per_frame; ns++) { - for (l=0; lframe_parms.symbols_per_slot; l++) { reset = 1; x2tmp0 = ((ue->frame_parms.symbols_per_slot*ns+l+1)*((nid<<1)+1))<<17; diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 83b43c54a0..1719457db8 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -57,8 +57,7 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue, void nr_gold_pbch(PHY_VARS_NR_UE* ue); void nr_gold_pdcch(PHY_VARS_NR_UE* ue, - unsigned short n_idDMRS, - unsigned short length_dmrs); + unsigned short n_idDMRS); void nr_gold_pdsch(PHY_VARS_NR_UE* ue, unsigned char ns, 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 6cb0a612e9..8407303c5e 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -512,6 +512,13 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, fr = filt16a_r1; + // checking if re-initialization of scrambling IDs is needed (should be done here but scrambling ID for PDCCH is not taken from RRC) +/* if (( != ue->scramblingID_pdcch){ + ue->scramblingID_pdcch=; + nr_gold_pdsch(ue,ue->scramblingID_pdcch); + }*/ + + // generate pilot int pilot[nb_rb_coreset * 3] __attribute__((aligned(16))); nr_pdcch_dmrs_rx(ue,eNB_offset,Ns,ue->nr_gold_pdcch[eNB_offset][Ns][symbol], &pilot[0],2000,nb_rb_coreset); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index f2a1a808d5..a176dab6c3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -316,7 +316,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, i ue->init_sync_frame = is; } - nr_gold_pdcch(ue,0, 2); /* int nb_prefix_samples0 = fp->nb_prefix_samples0; fp->nb_prefix_samples0 = fp->nb_prefix_samples; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 390574a66b..f27390cf66 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -842,9 +842,15 @@ typedef struct { /// PDSCH DMRS uint32_t ****nr_gold_pdsch[NUMBER_OF_CONNECTED_eNB_MAX]; + // Scrambling IDs used in PDSCH DMRS + uint16_t scramblingID[2]; + /// PDCCH DMRS uint32_t ***nr_gold_pdcch[NUMBER_OF_CONNECTED_eNB_MAX]; + // Scrambling IDs used in PDCCH DMRS + uint16_t scramblingID_pdcch; + /// PUSCH DMRS sequence uint32_t ****nr_gold_pusch_dmrs; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 835c839710..70edda043c 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1715,7 +1715,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, } #ifdef NR_PDCCH_SCHED - nr_gold_pdcch(ue, 0, 2); LOG_D(PHY," ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); for (uint16_t l=0; l Date: Tue, 6 Apr 2021 11:07:13 +0200 Subject: [PATCH 032/185] call for pdcch procedure for sib1 in initial sync --- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 35 ++++++++++++++++--- openair1/PHY/defs_nr_UE.h | 4 +++ openair1/SCHED_NR_UE/defs.h | 4 +++ openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 2 ++ openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 22 ++++++------ 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index a176dab6c3..246513bfe2 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -36,8 +36,7 @@ #include "PHY/MODULATION/modulation_UE.h" #include "nr_transport_proto_ue.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" -//#include "SCHED/defs.h" -//#include "SCHED/extern.h" +#include "SCHED_NR_UE/defs.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common_lib.h" @@ -46,6 +45,7 @@ #include "PHY/NR_REFSIG/pss_nr.h" #include "PHY/NR_REFSIG/sss_nr.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_TRANSPORT/nr_dci.h" extern openair0_config_t openair0_cfg[]; //static nfapi_nr_config_request_t config_t; @@ -478,9 +478,36 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, i #endif } - // if stand alone and sync on ssb - if (sa==1 && ret==0) { + // if stand alone and sync on ssb do sib1 detection as part of initial sync + if (sa==1 && ret==0) { + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; + uint8_t nb_symb_pdcch = pdcch_vars->nb_search_space > 0 ? pdcch_vars->pdcch_config[0].coreset.duration : 0; + + int coreset_nb_rb=0; + int coreset_start_rb=0; + + if (pdcch_vars->nb_search_space > 0) + get_coreset_rballoc(pdcch_vars->pdcch_config[0].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); + + for (uint16_t l=0; lslot, + pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); + + if (coreset_nb_rb > 0) + nr_pdcch_channel_estimation(ue, + proc, + 0, + pdcch_vars->slot, + l, + fp->first_carrier_offset+(pdcch_vars->pdcch_config[0].BWPStart + coreset_start_rb)*12, + coreset_nb_rb); + + } + int dci_cnt = nr_ue_pdcch_procedures(0, ue, proc); //gNB_id set to 0 } // exit_fun("debug exit"); diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index f27390cf66..db5daf7a89 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -635,6 +635,9 @@ typedef struct { uint8_t agregationLevel; int nb_search_space; fapi_nr_dl_config_dci_dl_pdu_rel15_t pdcch_config[FAPI_NR_MAX_SS_PER_CORESET]; + // frame and slot for sib1 in initial sync + uint16_t sfn; + uint16_t slot; /* #ifdef NR_PDCCH_DEFS_NR_UE int nb_searchSpaces; @@ -845,6 +848,7 @@ typedef struct { // Scrambling IDs used in PDSCH DMRS uint16_t scramblingID[2]; + /// PDCCH DMRS uint32_t ***nr_gold_pdcch[NUMBER_OF_CONNECTED_eNB_MAX]; diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index f7f44a520d..095c8ce2ed 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -416,6 +416,10 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch0, uint16_t n_pdus); +int nr_ue_pdcch_procedures(uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc); + #endif diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index e70c353589..85688f4ba6 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -75,6 +75,8 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ fapi_nr_dl_config_dci_dl_pdu_rel15_t *pdcch_config = &dl_config->dl_config_list[i].dci_config_pdu.dci_config_rel15; memcpy((void*)&pdcch_vars->pdcch_config[pdcch_vars->nb_search_space],(void*)pdcch_config,sizeof(*pdcch_config)); pdcch_vars->nb_search_space = pdcch_vars->nb_search_space + 1; + pdcch_vars->sfn = scheduled_response->frame; + pdcch_vars->slot = slot; LOG_D(PHY,"Number of DCI SearchSpaces %d\n",pdcch_vars->nb_search_space); } else { diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 70edda043c..58b3228271 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1731,18 +1731,18 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, dci_cnt = 0; for(int n_ss = 0; n_ssnb_search_space; n_ss++) { - // note: this only works if RBs for PDCCH are contigous! - LOG_D(PHY, "pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d\n", - fp->first_carrier_offset, pdcch_vars->pdcch_config[n_ss].BWPStart, coreset_start_rb); + // note: this only works if RBs for PDCCH are contigous! + LOG_D(PHY, "pdcch_channel_estimation: first_carrier_offset %d, BWPStart %d, coreset_start_rb %d\n", + fp->first_carrier_offset, pdcch_vars->pdcch_config[n_ss].BWPStart, coreset_start_rb); - if (coreset_nb_rb > 0) - nr_pdcch_channel_estimation(ue, - proc, - 0, - nr_slot_rx, - l, - fp->first_carrier_offset+(pdcch_vars->pdcch_config[n_ss].BWPStart + coreset_start_rb)*12, - coreset_nb_rb); + if (coreset_nb_rb > 0) + nr_pdcch_channel_estimation(ue, + proc, + 0, + nr_slot_rx, + l, + fp->first_carrier_offset+(pdcch_vars->pdcch_config[n_ss].BWPStart + coreset_start_rb)*12, + coreset_nb_rb); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_OUT); #if UE_TIMING_TRACE From 476e51fb90cb3b9f956cfdedb533b93e253890aa Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Wed, 7 Apr 2021 12:51:28 +0200 Subject: [PATCH 033/185] removing j from options --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 2d779c4471..a0aa02bf7b 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -349,7 +349,7 @@ int main(int argc, char **argv) FILE *scg_fd=NULL; - while ((c = getopt (argc, argv, "f:hA:pf:g:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:d:e:m:w:T:U:qi")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:in:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:d:e:m:w:T:U:q")) != -1) { switch (c) { case 'f': scg_fd = fopen(optarg,"r"); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index c8c2d95e53..bab893b356 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -284,7 +284,7 @@ int main(int argc, char **argv) /* initialize the sin-cos table */ InitSinLUT(); - while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:j:kl:m:n:p:r:s:y:z:F:G:H:M:N:PR:S:T:U:L:Zi")) != -1) { + while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:ikl:m:n:p:r:s:y:z:F:G:H:M:N:PR:S:T:U:L:Z")) != -1) { printf("handling optarg %c\n",c); switch (c) { From e2b35e684f1c37ddf16a02cc216f34c5a19d5da7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 8 Apr 2021 10:14:49 +0200 Subject: [PATCH 034/185] quick fix for nb antennas in frame parms --- openair1/PHY/INIT/nr_parms.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 35fa83f5fa..6a60ae6a68 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -368,6 +368,12 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink // setting initial ssb start subcarrier to have SSBs at BW center frame_parms->ssb_start_subcarrier = ((frame_parms->N_RB_DL>>1)-10)*12; + + if(frame_parms->nb_antennas_rx == 0) + frame_parms->nb_antennas_rx = 1; + if(frame_parms->nb_antennas_tx == 0) + frame_parms->nb_antennas_tx = 1; + } From 6ebb815eba29ec8775c273c0c2da8aa4216d38f8 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 9 Apr 2021 19:22:17 +0200 Subject: [PATCH 035/185] modifications in aggregation level for sib1 and decoding of dci at ue for sib1 --- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 1 - openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 1 - openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 27 ++-- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 1 + openair2/LAYER2/NR_MAC_UE/mac_proto.h | 10 +- .../NR_MAC_UE/nr_ue_dci_configuration.c | 3 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 146 ++++++++++-------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 59 +++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 11 +- 10 files changed, 148 insertions(+), 113 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 246513bfe2..d82e77c314 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -509,7 +509,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, i } int dci_cnt = nr_ue_pdcch_procedures(0, ue, proc); //gNB_id set to 0 } - // exit_fun("debug exit"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT); return ret; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 35af1d6d65..437e28b258 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -114,7 +114,6 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, dl_ind->dci_ind = NULL; } - } void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 0585d3e7f8..4f254a83a7 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3523,7 +3523,7 @@ void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_conf } -void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { +uint8_t fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, int L) { if(ss0 == NULL) ss0=calloc(1,sizeof(*ss0)); if(ss0->controlResourceSetId == NULL) ss0->controlResourceSetId=calloc(1,sizeof(*ss0->controlResourceSetId)); @@ -3536,11 +3536,13 @@ void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *ty ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss0->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); uint32_t duration,periodicity,offset; - uint16_t symbols,n_cces; + uint16_t symbols,max_agg; AssertFatal(type0_PDCCH_CSS_config!=NULL,"No type0 CSS configuration\n"); - n_cces = (type0_PDCCH_CSS_config->num_symbols*type0_PDCCH_CSS_config->num_rbs)/6; + max_agg = (type0_PDCCH_CSS_config->num_symbols*type0_PDCCH_CSS_config->num_rbs)/6; + if (L>max_agg) return 0; + symbols = (1-(1<num_symbols))<first_symbol_index; duration = type0_PDCCH_CSS_config->search_space_duration; periodicity = type0_PDCCH_CSS_config->search_space_frame_period; @@ -3569,24 +3571,31 @@ void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *ty ss0->monitoringSymbolsWithinSlot->buf[0] |= ((symbols>>i)&0x01)<<(7-i); } - // values according to TS38.213 Section 10.1 Table 10.1-1 + // max values are set according to TS38.213 Section 10.1 Table 10.1-1 ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - switch(n_cces){ + switch(L){ case 4: - ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; + ss0->nrofCandidates->aggregationLevel4 = (((max_agg>>2) > 4)? 4 : max_agg>>2); + ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; + ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; break; case 8: - ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n2; + ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n0; + ss0->nrofCandidates->aggregationLevel8 = (((max_agg>>3) > 2)? 2 : max_agg>>3); + ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; break; case 16: - ss0->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n1; + ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n0; + ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; + ss0->nrofCandidates->aggregationLevel16 = (((max_agg>>4) > 1)? 1 : max_agg>>4); break; default: - AssertFatal(1==0,"Invalid number of CCEs %d for SS0\n",n_cces); + AssertFatal(1==0,"Invalid aggregation level %d for SS0\n",L); } ss0->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; + return 1; } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 2723b85efb..bdd834f158 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -141,7 +141,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i_ssb); void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); -void fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); +uint8_t fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, int L); int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 11d27b6a2e..7535193ff8 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -308,6 +308,7 @@ typedef struct { typedef struct { NR_ServingCellConfigCommon_t *scc; + NR_ServingCellConfigCommonSIB_t *scc_SIB; NR_CellGroupConfig_t *scg; int servCellIndex; NR_CSI_ReportConfig_t *csirc; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 30d5b9eb41..a425ba29d2 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -179,12 +179,12 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, - uint8_t time_domain_ind); + uint8_t time_domain_ind, + bool use_default); -uint8_t -nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, - sub_frame_t subframe, uint8_t eNB_index, - uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) ; +uint8_t nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode); int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, int nrofDownlinkSlots, int nrofDownlinkSymbols, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index c8e071c239..909d7ab50b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -97,7 +97,8 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t for (int i = 0; i < 6; i++) rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i]; - rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; + rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == + NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) { struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved; rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index f0456ac6cb..3b823d313d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -259,9 +259,10 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, - uint8_t time_domain_ind - ){ - int dmrs_typeA_pos = mac->scc->dmrs_TypeA_Position; + uint8_t time_domain_ind, + bool use_default){ + + int dmrs_typeA_pos = (mac->scc != NULL) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position; // uint8_t k_offset=0; uint8_t sliv_S=0; uint8_t sliv_L=0; @@ -382,11 +383,13 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, */ if(dlsch_config_pdu != NULL){ NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = NULL; - if (mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList) + if (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList) pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->pdsch_TimeDomainAllocationList->choice.setup; - else if (mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList) + else if (mac->DLbwp[0] && mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList) pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; - if (pdsch_TimeDomainAllocationList) { + else if (mac->scc_SIB && mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup) + pdsch_TimeDomainAllocationList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + if (pdsch_TimeDomainAllocationList && use_default==false) { if (time_domain_ind >= pdsch_TimeDomainAllocationList->list.count) { LOG_E(MAC, "time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n", @@ -487,12 +490,10 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr RA_config_t *ra = &mac->ra; fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; uint8_t is_Msg3 = 0; - - //const uint16_t n_RB_DLBWP = dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP; //make sure this has been set - AssertFatal(mac->DLbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); - AssertFatal(mac->ULbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); - - const uint16_t n_RB_DLBWP = (ra->ra_state == WAIT_RAR) ? NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + printf("%p\n",mac->scg); + uint16_t n_RB_DLBWP = (mac->scg) ? + NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : + mac->type0_PDCCH_CSS_config.num_rbs; LOG_D(MAC, "In %s: Processing received DCI format %s (DL BWP %d)\n", __FUNCTION__, dci_formats[dci_format], n_RB_DLBWP); @@ -663,7 +664,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti; fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_0 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; - NR_PDSCH_Config_t *pdsch_config=mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup; + NR_PDSCH_Config_t *pdsch_config= (mac->scg) ? mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup : NULL; uint16_t BWPSize = 0; if(rnti == SI_RNTI) { @@ -671,7 +672,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs; dlsch_config_pdu_1_0->BWPStart = mac->type0_PDCCH_CSS_config.cset_start_rb; dlsch_config_pdu_1_0->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon; - pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL; // For PDSCH with mapping type A, the UE shall assume dmrs-AdditionalPosition='pos2' + if (pdsch_config) pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL; // For PDSCH with mapping type A, the UE shall assume dmrs-AdditionalPosition='pos2' BWPSize = dlsch_config_pdu_1_0->BWPSize; } else { if (ra->RA_window_cnt >= 0 && rnti == ra->ra_rnti){ @@ -692,15 +693,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr return -1; } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0) { + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val,rnti==SI_RNTI) < 0) { LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; } /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, - mac->scc->dmrs_TypeA_Position, - dlsch_config_pdu_1_0->start_symbol+dlsch_config_pdu_1_0->number_symbols); - dlsch_config_pdu_1_0->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + mac->mib->dmrs_TypeA_Position, + dlsch_config_pdu_1_0->number_symbols); + dlsch_config_pdu_1_0->dmrsConfigType = (mac->DLbwp[0] != NULL) ? + (mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1) : 0; + /* number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214 version 15.9.0 Release 15 */ if (dlsch_config_pdu_1_0->number_symbols == 2) dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 1; @@ -709,7 +712,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* VRB_TO_PRB_MAPPING */ dlsch_config_pdu_1_0->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; /* MCS TABLE INDEX */ - dlsch_config_pdu_1_0->mcs_table = (pdsch_config->mcs_Table) ? (*pdsch_config->mcs_Table + 1) : 0; + dlsch_config_pdu_1_0->mcs_table = (pdsch_config) ? ((pdsch_config->mcs_Table) ? (*pdsch_config->mcs_Table + 1) : 0) : 0; /* MCS */ dlsch_config_pdu_1_0->mcs = dci->mcs; // Basic sanity check for MCS value to check for a false or erroneous DCI @@ -749,18 +752,19 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->pucch_resource_id = dci->pucch_resource_indicator; // Sanity check for pucch_resource_indicator value received to check for false DCI. valid = 0; - pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count; - for (int id = 0; id < pucch_res_set_cnt; id++) { - if (dlsch_config_pdu_1_0->pucch_resource_id < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { - valid = 1; - break; + if (mac->scg) { + pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count; + for (int id = 0; id < pucch_res_set_cnt; id++) { + if (dlsch_config_pdu_1_0->pucch_resource_id < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + valid = 1; + break; + } + } + if (!valid) { + LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_0->pucch_resource_id); + return -1; } } - if (!valid) { - LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_0->pucch_resource_id); - return -1; - } - /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/ dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind = dci->pdsch_to_harq_feedback_timing_indicator.val; @@ -857,7 +861,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr return -1; } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0) { + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val,false) < 0) { LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; } @@ -1167,13 +1171,7 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *dci_pdu_rel15) { int rnti_type = get_rnti_type(mac, rnti); - - AssertFatal(mac->DLbwp[0] != NULL, "DLbwp[0] shouldn't be null here!\n"); - AssertFatal(mac->ULbwp[0] != NULL, "ULbwp[0] shouldn't be null here!\n"); - int N_RB = get_n_rb(mac, rnti_type); - int N_RB_UL = (mac->scg != NULL) ? - NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : - NRRIV2BW(mac->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int N_RB=0,N_RB_UL=0; int pos=0; int fsize=0; @@ -1183,6 +1181,10 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, case NR_DL_DCI_FORMAT_1_0: switch(rnti_type) { case NR_RNTI_RA: + // check BWP id + if (mac->scg) N_RB=NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + else N_RB=NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + // Freq domain assignment fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); pos=fsize; @@ -1219,6 +1221,10 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, case NR_RNTI_C: + // check BWP id + if (mac->scg) N_RB=NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + else N_RB=NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + //Identifier for DCI formats pos++; dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; @@ -1366,45 +1372,50 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, break; case NR_RNTI_SI: + N_RB = mac->type0_PDCCH_CSS_config.num_rbs; + // Freq domain assignment 0-16 bit + fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); + pos+=fsize; + dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<>1 ) ); - pos+=fsize; - dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1<time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf; - // Time domain assignment 4 bit - pos+=4; - dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf; + // VRB to PRB mapping 1 bit + pos++; + dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&0x1; - // VRB to PRB mapping 1 bit - pos++; - dci_pdu_rel15->vrb_to_prb_mapping.val = (*dci_pdu>>(dci_size-pos))&0x1; + // MCS 5bit //bit over 32, so dci_pdu ++ + pos+=5; + dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f; - // MCS 5bit //bit over 32, so dci_pdu ++ - pos+=5; - dci_pdu_rel15->mcs = (*dci_pdu>>(dci_size-pos))&0x1f; + // Redundancy version 2 bit + pos+=2; + dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&3; - // Redundancy version 2 bit - pos+=2; - dci_pdu_rel15->rv = (*dci_pdu>>(dci_size-pos))&3; + // System information indicator 1 bit + pos++; + dci_pdu_rel15->system_info_indicator = (*dci_pdu>>(dci_size-pos))&0x1; - // System information indicator 1 bit - pos++; - dci_pdu_rel15->system_info_indicator = (*dci_pdu>>(dci_size-pos))&0x1; - - LOG_D(MAC,"N_RB = %i\n", N_RB); - LOG_D(MAC,"dci_size = %i\n", dci_size); - LOG_D(MAC,"fsize = %i\n", fsize); - LOG_D(MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); - LOG_D(MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); - LOG_D(MAC,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val); - LOG_D(MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); - LOG_D(MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); - LOG_D(MAC,"dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator); + LOG_D(MAC,"N_RB = %i\n", N_RB); + LOG_D(MAC,"dci_size = %i\n", dci_size); + LOG_D(MAC,"fsize = %i\n", fsize); + LOG_D(MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + LOG_D(MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + LOG_D(MAC,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val); + LOG_D(MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); + LOG_D(MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + LOG_D(MAC,"dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator); break; case NR_RNTI_TC: + + // check BWP id + if (mac->scg) N_RB=NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + else N_RB=NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + // indicating a DL DCI format 1bit pos++; dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; @@ -1923,7 +1934,8 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, // WIP todo: handle CCCH_pdu mac_ce_len = 6; - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n", module_idP, frameP, pduP[0], pduP[1], pduP[2], pduP[3], pduP[4], pduP[5]); + LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n", + module_idP, frameP, pduP[0], pduP[1], pduP[2], pduP[3], pduP[4], pduP[5]); if (ra->RA_active == 1) { nr_ra_succeeded(module_idP, frameP, slot); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 1e43c7638e..c0d53a3076 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -665,7 +665,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, return -1; } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac, pusch_config_pdu, NULL, dci->time_domain_assignment.val) < 0) { + if (nr_ue_process_dci_time_dom_resource_assignment(mac, pusch_config_pdu, NULL, dci->time_domain_assignment.val,false) < 0) { return -1; } @@ -1749,7 +1749,9 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); nr_scheduled_response_t scheduled_response; - int frame_s,slot_s; + int frame_s,slot_s,ret; + fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; uint8_t scs_ssb = get_softmodem_params()->numerology; uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; @@ -1769,34 +1771,39 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, if(mac->search_space_zero == NULL) mac->search_space_zero=calloc(1,sizeof(*mac->search_space_zero)); if(mac->coreset0 == NULL) mac->coreset0 = calloc(1,sizeof(*mac->coreset0)); - fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); - fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config); + for (int i=0; i<3; i++) { // loop over possible aggregation levels - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; - rel15->num_dci_options = 1; - rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; - config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); - fill_dci_search_candidates(mac->search_space_zero, rel15); + fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); + ret = fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config,4<dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); + fill_dci_search_candidates(mac->search_space_zero, rel15); - if(mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern == 1){ - // same frame as ssb - if ((mac->type0_PDCCH_CSS_config.frame & 0x1) == mac->type0_PDCCH_CSS_config.sfn_c) - frame_s = 0; - else - frame_s = 1; - slot_s = mac->type0_PDCCH_CSS_config.n_0; + if(mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern == 1){ + // same frame as ssb + if ((mac->type0_PDCCH_CSS_config.frame & 0x1) == mac->type0_PDCCH_CSS_config.sfn_c) + frame_s = 0; + else + frame_s = 1; + slot_s = mac->type0_PDCCH_CSS_config.n_0; + } + else{ + frame_s = 0; // same frame as ssb + slot_s = mac->type0_PDCCH_CSS_config.n_c; + } + LOG_I(MAC,"Calling fill_scheduled_response, type0_pdcch, num_pdus %d\n",dl_config->number_pdus); + fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, module_idP, cc_id, frame_s, slot_s, 0); // TODO fix thread_id, for now assumed 0 + } } - else{ - frame_s = 0; // same frame as ssb - slot_s = mac->type0_PDCCH_CSS_config.n_c; + if (dl_config->number_pdus) { + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); } - - LOG_I(MAC,"Calling fill_scheduled_response, type0_pdcch, num_pdus %d\n",dl_config->number_pdus); - fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, module_idP, cc_id, frame_s, slot_s, 0); // TODO fix thread_id, for now assumed 0 - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) - mac->if_module->scheduled_response(&scheduled_response); - + else + AssertFatal(1==0,"Unable to find aggregation level for type0 CSS\n"); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 770246275a..a5f2356a3b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -321,13 +321,18 @@ void schedule_control_sib1(module_id_t module_id, gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; NR_ServingCellConfigCommon_t *servingcellconfigcommon = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; + int ret; if (gNB_mac->sched_ctrlCommon == NULL){ gNB_mac->sched_ctrlCommon = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon)); gNB_mac->sched_ctrlCommon->search_space = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->search_space)); gNB_mac->sched_ctrlCommon->coreset = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->coreset)); gNB_mac->sched_ctrlCommon->active_bwp = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->active_bwp)); - fill_searchSpaceZero(gNB_mac->sched_ctrlCommon->search_space,type0_PDCCH_CSS_config); + for (int i=0; i<3; i++){ // loop over possible aggregation levels + ret = fill_searchSpaceZero(gNB_mac->sched_ctrlCommon->search_space,type0_PDCCH_CSS_config,4<sched_ctrlCommon->coreset,type0_PDCCH_CSS_config); fill_default_initialDownlinkBWP(gNB_mac->sched_ctrlCommon->active_bwp,servingcellconfigcommon); } @@ -368,7 +373,9 @@ void schedule_control_sib1(module_id_t module_id, // Calculate number of PRB_DMRS uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6; - uint16_t dlDmrsSymbPos = fill_dmrs_mask(gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, startSymbolIndex+nrOfSymbols); + uint16_t dlDmrsSymbPos = fill_dmrs_mask(gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, + gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, + startSymbolIndex+nrOfSymbols); uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos); int rbSize = 0; From 913ac80093e940a62f12580b571ae9b1ccecc0c0 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 1 Mar 2021 20:41:02 +0100 Subject: [PATCH 036/185] Passing symbolStart to fill_dmrs_mask It is sufficient to pass l_d directly to the function but considering future extension to mapping type B, this way makes more sense. --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 8 +++-- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 5 +-- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 9 +++--- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 6 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 31 ++++++++++++------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 5 +-- 7 files changed, 40 insertions(+), 26 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 4f254a83a7..56f8a4d703 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2239,8 +2239,8 @@ int get_num_dmrs(uint16_t dmrs_mask ) { return(num_dmrs); } /* returns the total DMRS symbols in a slot*/ -uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols){ - return get_num_dmrs(fill_dmrs_mask(pdsch_Config,dmrs_TypeA_Position,NrOfSymbols)); +uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols,int startSymbol){ + return get_num_dmrs(fill_dmrs_mask(pdsch_Config,dmrs_TypeA_Position,NrOfSymbols,startSymbol)); } // Table 5.1.2.2.1-1 38.214 @@ -2879,9 +2879,10 @@ int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slot, lte_frame_type else return(slot_in_period >= slots1+scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); } -int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols) { +int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols,int startSymbol) { int l0; + int ld = NrOfSymbols; if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2) l0=2; else if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3) l0=3; else AssertFatal(1==0,"Illegal dmrs_TypeA_Position %d\n",(int)dmrs_TypeA_Position); @@ -2892,6 +2893,7 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) { // Relative to start of slot + ld += startSymbol; NR_DMRS_DownlinkConfig_t *dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; AssertFatal(NrOfSymbols>1 && NrOfSymbols < 15,"Illegal NrOfSymbols %d\n",NrOfSymbols); int pos2=0; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index bdd834f158..0523015712 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -47,7 +47,7 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw); -int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols); +int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols,int startSymbol); int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); @@ -156,7 +156,8 @@ bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, uint8_t *K_ptrs, uint8_t *L_ptrs, uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower, uint8_t NrOfSymbols); -uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols); + +uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols,int startSymbol); /* \brief Set the transform precoding according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16 @param *pusch_config, pointer to pusch config diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 3b823d313d..cb30e9f14d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -700,10 +700,10 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, mac->mib->dmrs_TypeA_Position, - dlsch_config_pdu_1_0->number_symbols); + dlsch_config_pdu_1_0->number_symbols, + dlsch_config_pdu_1_0->start_symbol); dlsch_config_pdu_1_0->dmrsConfigType = (mac->DLbwp[0] != NULL) ? (mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1) : 0; - /* number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214 version 15.9.0 Release 15 */ if (dlsch_config_pdu_1_0->number_symbols == 2) dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 1; @@ -867,8 +867,9 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } /* dmrs symbol positions*/ dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, - mac->scc->dmrs_TypeA_Position, - dlsch_config_pdu_1_1->number_symbols); + mac->scc->dmrs_TypeA_Position, + dlsch_config_pdu_1_1->number_symbols, + dlsch_config_pdu_1_1->start_symbol); dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[dl_bwp_id-1]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; /* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214, using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index bc297225af..186fe34e81 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1013,7 +1013,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; - pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, NrOfSymbols); + pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, NrOfSymbols, StartSymbolIndex); pdsch_pdu_rel15->precodingAndBeamforming.num_prgs=1; pdsch_pdu_rel15->precodingAndBeamforming.prg_size=275; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index a5f2356a3b..d32c6186b0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -375,7 +375,7 @@ void schedule_control_sib1(module_id_t module_id, uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6; uint16_t dlDmrsSymbPos = fill_dmrs_mask(gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, - startSymbolIndex+nrOfSymbols); + nrOfSymbols, startSymbolIndex); uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos); int rbSize = 0; @@ -479,7 +479,7 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; - pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup, scc->dmrs_TypeA_Position, pdsch_pdu_rel15->StartSymbolIndex+pdsch_pdu_rel15->NrOfSymbols); + pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup, scc->dmrs_TypeA_Position, pdsch_pdu_rel15->NrOfSymbols, pdsch_pdu_rel15->StartSymbolIndex); LOG_D(MAC,"dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos); @@ -604,7 +604,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) // Calculate number of PRB_DMRS uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6; uint16_t dlDmrsSymbPos = fill_dmrs_mask(gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, - gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, startSymbolIndex+nrOfSymbols); + gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, startSymbolIndex, nrOfSymbols); uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos); const uint32_t TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 30a89cce77..296b271df5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -302,7 +302,7 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, return offset; } -int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda) { +void getStartNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda, int *startSymbol, int *nrOfSymbols) { struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; AssertFatal(tda < tdaList->list.count, @@ -311,9 +311,7 @@ int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda) { tdaList->list.count); const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength; - int startSymbolIndex, nrOfSymbols; - SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); - return nrOfSymbols; + SLIV2SL(startSymbolAndLength, startSymbol, nrOfSymbols); } nfapi_nr_dmrs_type_e getDmrsConfigType(NR_BWP_Downlink_t *bwp) { @@ -487,8 +485,12 @@ void pf_dl(module_id_t module_id, sched_ctrl->numDmrsCdmGrpsNoData = 1; uint8_t N_PRB_DMRS = getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData); - int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp, - sched_ctrl->time_domain_allocation); + int startSymbol; + int nrOfSymbols; + getStartNrOfSymbols(sched_ctrl->active_bwp, + sched_ctrl->time_domain_allocation, + &startSymbol, + &nrOfSymbols); uint32_t tbs = nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), 1, // rbSize @@ -574,13 +576,18 @@ void pf_dl(module_id_t module_id, const uint8_t N_PRB_DMRS = getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData); - const int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp, - sched_ctrl->time_domain_allocation); + int startSymbol; + int nrOfSymbols; + getStartNrOfSymbols(sched_ctrl->active_bwp, + sched_ctrl->time_domain_allocation, + &startSymbol, + &nrOfSymbols); const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels->ServingCellConfigCommon; const uint8_t N_DMRS_SLOT = get_num_dmrs_symbols( sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, scc->dmrs_TypeA_Position, - nrOfSymbols); + nrOfSymbols, + startSymbol); int rbSize = 0; uint32_t TBS = 0; @@ -697,7 +704,8 @@ void nr_schedule_ue_spec(module_id_t module_id, getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData); uint8_t N_DMRS_SLOT = get_num_dmrs_symbols(sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, RC.nrmac[module_id]->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position , - nrOfSymbols); + nrOfSymbols, + startSymbolIndex); const nfapi_nr_dmrs_type_e dmrsConfigType = getDmrsConfigType(sched_ctrl->active_bwp); const int nrOfLayers = 1; const uint16_t R = nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx); @@ -818,7 +826,8 @@ void nr_schedule_ue_spec(module_id_t module_id, pdsch_pdu->dlDmrsSymbPos = fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup, scc->dmrs_TypeA_Position, - nrOfSymbols); + nrOfSymbols, + startSymbolIndex); pdsch_pdu->dmrsConfigType = dmrsConfigType; pdsch_pdu->dlDmrsScramblingId = *scc->physCellId; pdsch_pdu->SCID = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 6487f391b9..089f1020e1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -163,8 +163,9 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, - scc->dmrs_TypeA_Position, - NrOfSymbols); + scc->dmrs_TypeA_Position, + NrOfSymbols, + StartSymbolIndex); /* AssertFatal(k0==0,"k0 is not zero for Initial DL BWP TimeDomain Alloc\n"); From f2127adf406ee9ad45567ebdd6466159ec0bbbfa Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 12 Apr 2021 11:22:16 +0200 Subject: [PATCH 037/185] reworking of pdcch procedures function call --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 234 +++++++++--------- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 39 +-- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 6 +- openair1/SCHED_NR_UE/defs.h | 3 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 24 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- 6 files changed, 156 insertions(+), 152 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 8176514eb4..f36f6c8242 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -699,102 +699,100 @@ void pdcch_siso(NR_DL_FRAME_PARMS *frame_parms, #ifdef NR_PDCCH_DCI_RUN int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc) { + UE_nr_rxtx_proc_t *proc, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) { uint32_t frame = proc->frame_rx; uint32_t slot = proc->nr_slot_rx; NR_UE_COMMON *common_vars = &ue->common_vars; NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; uint8_t log2_maxh, aarx; int32_t avgs; int32_t avgP[4]; - for (int i=0;inb_search_space;i++) { - rel15 = &pdcch_vars->pdcch_config[i]; - int n_rb,rb_offset; - get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); - for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { - LOG_D(PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); + int n_rb,rb_offset; + get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); + for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { + LOG_D(PHY,"in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); - nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, - pdcch_vars->dl_ch_estimates, - pdcch_vars->rxdataF_ext, - pdcch_vars->dl_ch_estimates_ext, - s, - frame_parms, - rel15->coreset.frequency_domain_resource, - n_rb, - rel15->BWPStart); + nr_pdcch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, + pdcch_vars->dl_ch_estimates, + pdcch_vars->rxdataF_ext, + pdcch_vars->dl_ch_estimates_ext, + s, + frame_parms, + rel15->coreset.frequency_domain_resource, + n_rb, + rel15->BWPStart); - LOG_D(PHY,"we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",*avgP); - LOG_D(PHY,"in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); - // compute channel level based on ofdm symbol 0 - nr_pdcch_channel_level(pdcch_vars->dl_ch_estimates_ext, - frame_parms, - avgP, - n_rb); - avgs = 0; + LOG_D(PHY,"we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, pdcch_vars[eNB_id]->dl_ch_estimates_ext\n",*avgP); + LOG_D(PHY,"in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); + // compute channel level based on ofdm symbol 0 + nr_pdcch_channel_level(pdcch_vars->dl_ch_estimates_ext, + frame_parms, + avgP, + n_rb); + avgs = 0; - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) - avgs = cmax(avgs, avgP[aarx]); + for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) + avgs = cmax(avgs, avgP[aarx]); - log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; + log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; #ifdef UE_DEBUG_TRACE - LOG_D(PHY,"slot %d: pdcch log2_maxh = %d (%d,%d)\n",slot,log2_maxh,avgP[0],avgs); + LOG_D(PHY,"slot %d: pdcch log2_maxh = %d (%d,%d)\n",slot,log2_maxh,avgP[0],avgs); #endif #if T_TRACER - T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(frame%1024), T_INT(slot), - T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); + T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(frame%1024), T_INT(slot), + T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); #endif - LOG_D(PHY,"we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh); - LOG_D(PHY,"in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); - // compute LLRs for ofdm symbol 0 only - nr_pdcch_channel_compensation(pdcch_vars->rxdataF_ext, - pdcch_vars->dl_ch_estimates_ext, - pdcch_vars->rxdataF_comp, - NULL, - frame_parms, - s, - log2_maxh, - n_rb); // log2_maxh+I0_shift - if (frame_parms->nb_antennas_rx > 1) { - LOG_D(PHY,"we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); - nr_pdcch_detection_mrc(frame_parms, pdcch_vars->rxdataF_comp,s); - } + LOG_D(PHY,"we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh); + LOG_D(PHY,"in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); + // compute LLRs for ofdm symbol 0 only + nr_pdcch_channel_compensation(pdcch_vars->rxdataF_ext, + pdcch_vars->dl_ch_estimates_ext, + pdcch_vars->rxdataF_comp, + NULL, + frame_parms, + s, + log2_maxh, + n_rb); // log2_maxh+I0_shift + if (frame_parms->nb_antennas_rx > 1) { + LOG_D(PHY,"we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); + nr_pdcch_detection_mrc(frame_parms, pdcch_vars->rxdataF_comp,s); + } - LOG_D(PHY,"we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s); - LOG_D(PHY,"in nr_pdcch_llr(rxdataF_comp -> llr)\n"); - nr_pdcch_llr(frame_parms, - pdcch_vars->rxdataF_comp, - pdcch_vars->llr, - s, - n_rb); + LOG_D(PHY,"we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n",s); + LOG_D(PHY,"in nr_pdcch_llr(rxdataF_comp -> llr)\n"); + nr_pdcch_llr(frame_parms, + pdcch_vars->rxdataF_comp, + pdcch_vars->llr, + s, + n_rb); #if T_TRACER - // T(T_UE_PHY_PDCCH_IQ, T_INT(frame_parms->N_RB_DL), T_INT(frame_parms->N_RB_DL), - // T_INT(n_pdcch_symbols), - // T_BUFFER(pdcch_vars[eNB_id]->rxdataF_comp, frame_parms->N_RB_DL*12*n_pdcch_symbols* 4)); + // T(T_UE_PHY_PDCCH_IQ, T_INT(frame_parms->N_RB_DL), T_INT(frame_parms->N_RB_DL), + // T_INT(n_pdcch_symbols), + // T_BUFFER(pdcch_vars[eNB_id]->rxdataF_comp, frame_parms->N_RB_DL*12*n_pdcch_symbols* 4)); #endif #ifdef DEBUG_DCI_DECODING - printf("demapping: slot %d, mi %d\n",slot,get_mi(frame_parms,slot)); + printf("demapping: slot %d, mi %d\n",slot,get_mi(frame_parms,slot)); #endif - } + } - LOG_D(PHY,"we enter nr_pdcch_demapping_deinterleaving()\n"); - nr_pdcch_demapping_deinterleaving((uint32_t *) pdcch_vars->llr, - (uint32_t *) pdcch_vars->e_rx, - rel15->coreset.duration, - n_rb, - rel15->coreset.RegBundleSize, - rel15->coreset.InterleaverSize, - rel15->coreset.ShiftIndex, - rel15->number_of_candidates, - rel15->CCE, - rel15->L); + LOG_D(PHY,"we enter nr_pdcch_demapping_deinterleaving()\n"); + nr_pdcch_demapping_deinterleaving((uint32_t *) pdcch_vars->llr, + (uint32_t *) pdcch_vars->e_rx, + rel15->coreset.duration, + n_rb, + rel15->coreset.RegBundleSize, + rel15->coreset.InterleaverSize, + rel15->coreset.ShiftIndex, + rel15->number_of_candidates, + rel15->CCE, + rel15->L); /* nr_pdcch_unscrambling(rel15->rnti, frame_parms, @@ -804,10 +802,9 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, // get_nCCE(n_pdcch_symbols, frame_parms, mi) * 72, rel15->coreset.pdcch_dmrs_scrambling_id); */ - LOG_D(PHY,"we end nr_pdcch_unscrambling()\n"); - LOG_D(PHY,"Ending nr_rx_pdcch() function\n"); + LOG_D(PHY,"we end nr_pdcch_unscrambling()\n"); + LOG_D(PHY,"Ending nr_rx_pdcch() function\n"); - } return (0); } @@ -876,63 +873,60 @@ void nr_pdcch_unscrambling(int16_t *z, #ifdef NR_PDCCH_DCI_RUN uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, - fapi_nr_dci_indication_t *dci_ind) { + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) { - NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; - for (int i=0;inb_search_space;i++) { + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; - rel15 = &pdcch_vars->pdcch_config[i]; - //int gNB_id = 0; - int16_t tmp_e[16*108]; - rnti_t n_rnti; + //int gNB_id = 0; + int16_t tmp_e[16*108]; + rnti_t n_rnti; - for (int j=0;jnumber_of_candidates;j++) { - int CCEind = rel15->CCE[j]; - int L = rel15->L[j]; + for (int j=0;jnumber_of_candidates;j++) { + int CCEind = rel15->CCE[j]; + int L = rel15->L[j]; - // Loop over possible DCI lengths - for (int k = 0; k < rel15->num_dci_options; k++) { - int dci_length = rel15->dci_length_options[k]; - uint64_t dci_estimation[2]= {0}; - const t_nrPolar_params *currentPtrDCI = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L, 1, &ue->polarList); + // Loop over possible DCI lengths + for (int k = 0; k < rel15->num_dci_options; k++) { + int dci_length = rel15->dci_length_options[k]; + uint64_t dci_estimation[2]= {0}; + const t_nrPolar_params *currentPtrDCI = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE, dci_length, L, 1, &ue->polarList); - LOG_D(PHY, "Trying DCI candidate %d of %d number of candidates, CCE %d (%d), L %d\n", j, rel15->number_of_candidates, CCEind, CCEind*9*6*2, L); + LOG_D(PHY, "Trying DCI candidate %d of %d number of candidates, CCE %d (%d), L %d\n", j, rel15->number_of_candidates, CCEind, CCEind*9*6*2, L); - nr_pdcch_unscrambling(&pdcch_vars->e_rx[CCEind*108], rel15->coreset.scrambling_rnti, L*108, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e); + nr_pdcch_unscrambling(&pdcch_vars->e_rx[CCEind*108], rel15->coreset.scrambling_rnti, L*108, rel15->coreset.pdcch_dmrs_scrambling_id, tmp_e); - #ifdef DEBUG_DCI_DECODING - uint32_t * z = (uint32_t *) &pdcch_vars->e_rx[CCEind*108]; - for (int index_z = 0; index_z < 96; index_z++){ - for (int i=0; i<9; i++) { - LOG_D(PHY,"z[%d]=(%d,%d) \n", (9*index_z + i), *(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i])); - } - } - #endif - - uint16_t crc = polar_decoder_int16(tmp_e, - dci_estimation, - 1, - currentPtrDCI); - - n_rnti = rel15->rnti; - - if (crc == n_rnti) { - LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", - proc->frame_rx, proc->nr_slot_rx,n_rnti,rel15->dci_format_options[k],CCEind,dci_length,*(unsigned long long*)dci_estimation); - dci_ind->SFN = proc->frame_rx; - dci_ind->slot = proc->nr_slot_rx; - dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti; - dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind; - dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k]; - dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length; - memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8); - dci_ind->number_of_dcis++; - break; // If DCI is found, no need to check for remaining DCI lengths - } else { - LOG_D(PHY,"(%i.%i) Decoded crc %x does not match rnti %x for DCI format %d\n", proc->frame_rx, proc->nr_slot_rx, crc, n_rnti, rel15->dci_format_options[k]); +#ifdef DEBUG_DCI_DECODING + uint32_t * z = (uint32_t *) &pdcch_vars->e_rx[CCEind*108]; + for (int index_z = 0; index_z < 96; index_z++){ + for (int i=0; i<9; i++) { + LOG_D(PHY,"z[%d]=(%d,%d) \n", (9*index_z + i), *(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i])); } } +#endif + + uint16_t crc = polar_decoder_int16(tmp_e, + dci_estimation, + 1, + currentPtrDCI); + + n_rnti = rel15->rnti; + + if (crc == n_rnti) { + LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", + proc->frame_rx, proc->nr_slot_rx,n_rnti,rel15->dci_format_options[k],CCEind,dci_length,*(unsigned long long*)dci_estimation); + dci_ind->SFN = proc->frame_rx; + dci_ind->slot = proc->nr_slot_rx; + dci_ind->dci_list[dci_ind->number_of_dcis].rnti = n_rnti; + dci_ind->dci_list[dci_ind->number_of_dcis].n_CCE = CCEind; + dci_ind->dci_list[dci_ind->number_of_dcis].dci_format = rel15->dci_format_options[k]; + dci_ind->dci_list[dci_ind->number_of_dcis].payloadSize = dci_length; + memcpy((void*)dci_ind->dci_list[dci_ind->number_of_dcis].payloadBits,(void*)dci_estimation,8); + dci_ind->number_of_dcis++; + break; // If DCI is found, no need to check for remaining DCI lengths + } else { + LOG_D(PHY,"(%i.%i) Decoded crc %x does not match rnti %x for DCI format %d\n", proc->frame_rx, proc->nr_slot_rx, crc, n_rnti, rel15->dci_format_options[k]); + } } } return(dci_ind->number_of_dcis); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index d82e77c314..a58756b708 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -483,31 +483,34 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, i if (sa==1 && ret==0) { NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; uint8_t nb_symb_pdcch = pdcch_vars->nb_search_space > 0 ? pdcch_vars->pdcch_config[0].coreset.duration : 0; - int coreset_nb_rb=0; int coreset_start_rb=0; - if (pdcch_vars->nb_search_space > 0) - get_coreset_rballoc(pdcch_vars->pdcch_config[0].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); + for(int n_ss = 0; n_ssnb_search_space; n_ss++) { + get_coreset_rballoc(pdcch_vars->pdcch_config[n_ss].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); - for (uint16_t l=0; lslot, - pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); + for (uint16_t l=0; lslot, + pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); - if (coreset_nb_rb > 0) - nr_pdcch_channel_estimation(ue, - proc, - 0, - pdcch_vars->slot, - l, - fp->first_carrier_offset+(pdcch_vars->pdcch_config[0].BWPStart + coreset_start_rb)*12, - coreset_nb_rb); + if (coreset_nb_rb > 0) + nr_pdcch_channel_estimation(ue, + proc, + 0, + pdcch_vars->slot, + l, + fp->first_carrier_offset+(pdcch_vars->pdcch_config[n_ss].BWPStart + coreset_start_rb)*12, + coreset_nb_rb); + } + int dci_cnt = nr_ue_pdcch_procedures(0, ue, proc, n_ss); //gNB_id set to 0 + if (dci_cnt>0){ + break; + } } - int dci_cnt = nr_ue_pdcch_procedures(0, ue, proc); //gNB_id set to 0 } // exit_fun("debug exit"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index fd0af7f1b0..af02b4aa36 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1120,7 +1120,8 @@ uint32_t dlsch_decoding_emul(PHY_VARS_NR_UE *phy_vars_ue, uint8_t eNB_id); int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc); + UE_nr_rxtx_proc_t *proc, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); /*! \brief Extract PSS and SSS resource elements @@ -1709,7 +1710,8 @@ uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset); uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, - fapi_nr_dci_indication_t *dci_ind); + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15); /** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation. It performs diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 095c8ce2ed..52af5f733b 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -418,7 +418,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, int nr_ue_pdcch_procedures(uint8_t gNB_id, PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc); + UE_nr_rxtx_proc_t *proc, + int n_ss); #endif diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 437e28b258..38f4ec1c02 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -477,7 +477,8 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb int nr_ue_pdcch_procedures(uint8_t gNB_id, PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc) + UE_nr_rxtx_proc_t *proc, + int n_ss) { int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; @@ -485,6 +486,9 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, fapi_nr_dci_indication_t dci_ind = {0}; nr_downlink_indication_t dl_indication; + NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][gNB_id]; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &pdcch_vars->pdcch_config[n_ss]; + /* // unsigned int dci_cnt=0, i; //removed for nr_ue_pdcch_procedures and added in the loop for nb_coreset_active #ifdef NR_PDCCH_SCHED_DEBUG @@ -669,18 +673,18 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, */ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN); - nr_rx_pdcch(ue, proc); + nr_rx_pdcch(ue, proc, rel15); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING, VCD_FUNCTION_IN); #ifdef NR_PDCCH_SCHED_DEBUG - printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_dci_decoding_procedure with (nb_searchspace_active=%d)\n", - pdcch_vars->nb_search_space); + printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_dci_decoding_procedure for search space %d)\n", + n_ss); #endif - dci_cnt = nr_dci_decoding_procedure(ue, proc, &dci_ind); + dci_cnt = nr_dci_decoding_procedure(ue, proc, &dci_ind, rel15); #ifdef NR_PDCCH_SCHED_DEBUG LOG_I(PHY,"<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_dci_decoding_procedure() -> dci_cnt=%u\n",dci_cnt); @@ -1708,10 +1712,11 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, proc, l, nr_slot_rx); + } - dci_cnt = 0; - for(int n_ss = 0; n_ssnb_search_space; n_ss++) { - + dci_cnt = 0; + for(int n_ss = 0; n_ssnb_search_space; n_ss++) { + for (uint16_t l=0; lfirst_carrier_offset, pdcch_vars->pdcch_config[n_ss].BWPStart, coreset_start_rb); @@ -1728,9 +1733,8 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, #if UE_TIMING_TRACE stop_meas(&ue->ofdm_demod_stats); #endif - - dci_cnt = dci_cnt + nr_ue_pdcch_procedures(gNB_id, ue, proc); } + dci_cnt = dci_cnt + nr_ue_pdcch_procedures(gNB_id, ue, proc, n_ss); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index cb30e9f14d..17b50cd5b9 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -490,7 +490,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr RA_config_t *ra = &mac->ra; fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; uint8_t is_Msg3 = 0; - printf("%p\n",mac->scg); + uint16_t n_RB_DLBWP = (mac->scg) ? NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : mac->type0_PDCCH_CSS_config.num_rbs; From 99a56f0530113647a60c266220f553c1db3252e8 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 31 Mar 2021 14:31:19 +0100 Subject: [PATCH 038/185] Rework default PDSCH time domain resource allocation tables --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 146 ++++++++++++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h | 9 ++ openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 91 ++--------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 29 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 1 - .../gnb.sa.band41.fr1.106PRB.usrpb210.conf | 8 +- .../gnb.sa.band78.fr1.106PRB.usrpb210.conf | 8 +- 7 files changed, 195 insertions(+), 97 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 56f8a4d703..d4e5e9c2c2 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -125,6 +125,152 @@ const float table_38213_13_12_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 0.5f, 0.5f const int32_t table_38213_10_1_1_c2[5] = { 0, 0, 4, 2, 1 }; +// for PDSCH from TS 38.214 subclause 5.1.2.1.1 +const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[16][3]={ + {0,2,12}, // row index 1 + {0,2,10}, // row index 2 + {0,2,9}, // row index 3 + {0,2,7}, // row index 4 + {0,2,5}, // row index 5 + {0,9,4}, // row index 6 + {0,4,4}, // row index 7 + {0,5,7}, // row index 8 + {0,5,2}, // row index 9 + {0,9,2}, // row index 10 + {0,12,2}, // row index 11 + {0,1,13}, // row index 12 + {0,1,6}, // row index 13 + {0,2,4}, // row index 14 + {0,4,7}, // row index 15 + {0,8,4} // row index 16 +}; +const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[16][3]={ + {0,3,11}, // row index 1 + {0,3,9}, // row index 2 + {0,3,8}, // row index 3 + {0,3,6}, // row index 4 + {0,3,4}, // row index 5 + {0,10,4}, // row index 6 + {0,6,4}, // row index 7 + {0,5,7}, // row index 8 + {0,5,2}, // row index 9 + {0,9,2}, // row index 10 + {0,12,2}, // row index 11 + {0,1,13}, // row index 12 + {0,1,6}, // row index 13 + {0,2,4}, // row index 14 + {0,4,7}, // row index 15 + {0,8,4} // row index 16 +}; +const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[16][3]={ + {0,2,6}, // row index 1 + {0,2,10}, // row index 2 + {0,2,9}, // row index 3 + {0,2,7}, // row index 4 + {0,2,5}, // row index 5 + {0,6,4}, // row index 6 + {0,4,4}, // row index 7 + {0,5,6}, // row index 8 + {0,5,2}, // row index 9 + {0,9,2}, // row index 10 + {0,10,2}, // row index 11 + {0,1,11}, // row index 12 + {0,1,6}, // row index 13 + {0,2,4}, // row index 14 + {0,4,6}, // row index 15 + {0,8,4} // row index 16 +}; +const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[16][3]={ + {0,3,5}, // row index 1 + {0,3,9}, // row index 2 + {0,3,8}, // row index 3 + {0,3,6}, // row index 4 + {0,3,4}, // row index 5 + {0,8,2}, // row index 6 + {0,6,4}, // row index 7 + {0,5,6}, // row index 8 + {0,5,2}, // row index 9 + {0,9,2}, // row index 10 + {0,10,2}, // row index 11 + {0,1,11}, // row index 12 + {0,1,6}, // row index 13 + {0,2,4}, // row index 14 + {0,4,6}, // row index 15 + {0,8,4} // row index 16 +}; +const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[16][3]={ + {0,2,2}, // row index 1 + {0,4,2}, // row index 2 + {0,6,2}, // row index 3 + {0,8,2}, // row index 4 + {0,10,2}, // row index 5 + {1,2,2}, // row index 6 + {1,4,2}, // row index 7 + {0,2,4}, // row index 8 + {0,4,4}, // row index 9 + {0,6,4}, // row index 10 + {0,8,4}, // row index 11 + {0,10,4}, // row index 12 + {0,2,7}, // row index 13 + {0,2,12}, // row index 14 + {1,2,4}, // row index 15 + {0,0,0} // row index 16 +}; +const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[16][3]={ + {0,2,2}, // row index 1 + {0,4,2}, // row index 2 + {0,6,2}, // row index 3 + {0,8,2}, // row index 4 + {0,10,2}, // row index 5 + {1,2,2}, // row index 6 + {1,4,2}, // row index 7 + {0,2,4}, // row index 8 + {0,4,4}, // row index 9 + {0,6,4}, // row index 10 + {0,8,4}, // row index 11 + {0,10,4}, // row index 12 + {0,2,7}, // row index 13 + {0,3,11}, // row index 14 + {1,2,4}, // row index 15 + {0,0,0} // row index 16 +}; +const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[16][3]={ + {0,2,2}, // row index 1 + {0,4,2}, // row index 2 + {0,6,2}, // row index 3 + {0,8,2}, // row index 4 + {0,10,2}, // row index 5 + {0,0,0}, // row index 6 + {0,0,0}, // row index 7 + {0,2,4}, // row index 8 + {0,4,4}, // row index 9 + {0,6,4}, // row index 10 + {0,8,4}, // row index 11 + {0,10,4}, // row index 12 + {0,2,7}, // row index 13 + {0,2,12}, // row index 14 + {0,0,6}, // row index 15 + {0,2,6} // row index 16 +}; +const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[16][3]={ + {0,2,2}, // row index 1 + {0,4,2}, // row index 2 + {0,6,2}, // row index 3 + {0,8,2}, // row index 4 + {0,10,2}, // row index 5 + {0,0,0}, // row index 6 + {0,0,0}, // row index 7 + {0,2,4}, // row index 8 + {0,4,4}, // row index 9 + {0,6,4}, // row index 10 + {0,8,4}, // row index 11 + {0,10,4}, // row index 12 + {0,2,7}, // row index 13 + {0,3,11}, // row index 14 + {0,0,6}, // row index 15 + {0,2,6} // row index 16 +}; + const char *prachfmt[]={"0","1","2","3", "A1","A2","A3","B1","B4","C0","C2","A1/B1","A2/B2","A3/B3"}; const char *duplex_mode[]={"FDD","TDD"}; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h index 8f7a726bb8..1e0ab98d4c 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h @@ -139,4 +139,13 @@ extern const float table_38213_13_12_c3[16]; extern const int32_t table_38213_10_1_1_c2[5]; +extern const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[16][3]; +extern const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[16][3]; +extern const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[16][3]; +extern const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[16][3]; +extern const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[16][3]; +extern const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[16][3]; +extern const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[16][3]; +extern const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[16][3]; + #endif //DEF_H diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 17b50cd5b9..3ce8403f67 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -263,82 +263,12 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, bool use_default){ int dmrs_typeA_pos = (mac->scc != NULL) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position; + // uint8_t k_offset=0; uint8_t sliv_S=0; uint8_t sliv_L=0; - uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?12:11}, // row index 1 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?10:9}, // row index 2 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?9:8}, // row index 3 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?7:6}, // row index 4 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?5:4}, // row index 5 - {0,(dmrs_typeA_pos == 0)?9:10,(dmrs_typeA_pos == 0)?4:4}, // row index 6 - {0,(dmrs_typeA_pos == 0)?4:6, (dmrs_typeA_pos == 0)?4:4}, // row index 7 - {0,5,7}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,12,2}, // row index 11 - {0,1,13}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,7}, // row index 15 - {0,8,4} // row index 16 - }; - /*uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?6:5}, // row index 1 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?10:9}, // row index 2 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?9:8}, // row index 3 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?7:6}, // row index 4 - {0,(dmrs_typeA_pos == 0)?2:3, (dmrs_typeA_pos == 0)?5:4}, // row index 5 - {0,(dmrs_typeA_pos == 0)?6:8, (dmrs_typeA_pos == 0)?4:2}, // row index 6 - {0,(dmrs_typeA_pos == 0)?4:6, (dmrs_typeA_pos == 0)?4:4}, // row index 7 - {0,5,6}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,10,2}, // row index 11 - {0,1,11}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,6}, // row index 15 - {0,8,4} // row index 16 - };*/ - /*uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,2,2}, // row index 1 - {0,4,2}, // row index 2 - {0,6,2}, // row index 3 - {0,8,2}, // row index 4 - {0,10,2}, // row index 5 - {1,2,2}, // row index 6 - {1,4,2}, // row index 7 - {0,2,4}, // row index 8 - {0,4,4}, // row index 9 - {0,6,4}, // row index 10 - {0,8,4}, // row index 11 - {0,10,4}, // row index 12 - {0,2,7}, // row index 13 - {0,(dmrs_typeA_pos == 0)?2:3,(dmrs_typeA_pos == 0)?12:11}, // row index 14 - {1,2,4}, // row index 15 - {0,0,0} // row index 16 - };*/ - /*uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,2,2}, // row index 1 - {0,4,2}, // row index 2 - {0,6,2}, // row index 3 - {0,8,2}, // row index 4 - {0,10,2}, // row index 5 - {0,0,0}, // row index 6 - {0,0,0}, // row index 7 - {0,2,4}, // row index 8 - {0,4,4}, // row index 9 - {0,6,4}, // row index 10 - {0,8,4}, // row index 11 - {0,10,4}, // row index 12 - {0,2,7}, // row index 13 - {0,(dmrs_typeA_pos == 0)?2:3,(dmrs_typeA_pos == 0)?12:11}, // row index 14 - {0,0,6}, // row index 15 - {0,2,6} // row index 16 - };*/ uint8_t mu_pusch = 1; + // definition table j Table 6.1.2.1.1-4 uint8_t j = (mu_pusch==3)?3:(mu_pusch==2)?2:1; uint8_t table_6_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PUSCH from TS 38.214 subclause 6.1.2.1.1 @@ -412,8 +342,15 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, } else {// Default configuration from tables // k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; - sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1]; - sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2]; + + if(dmrs_typeA_pos == 0) { + sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[time_domain_ind][1]; + sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[time_domain_ind][2]; + } else { + sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[time_domain_ind][1]; + sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[time_domain_ind][2]; + } + // k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; // sliv_S = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1]; // sliv_L = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2]; @@ -438,7 +375,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; } - if (pusch_TimeDomainAllocationList) { + if (pusch_TimeDomainAllocationList && use_default==false) { if (time_domain_ind >= pusch_TimeDomainAllocationList->list.count) { LOG_E(MAC, "time_domain_ind %d >= pusch->TimeDomainAllocationList->list.count %d\n", time_domain_ind, pusch_TimeDomainAllocationList->list.count); @@ -455,8 +392,8 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, } else { // k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; - sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1]; - sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2]; + sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind][1]; + sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind][2]; // k_offset = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; // sliv_S = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1]; // sliv_L = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index d32c6186b0..b10faddfbb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -359,11 +359,15 @@ void schedule_control_sib1(module_id_t module_id, const uint16_t bwpSize = type0_PDCCH_CSS_config->num_rbs; int rbStart = type0_PDCCH_CSS_config->cset_start_rb; - // Calculate number of symbols - struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; - const int startSymbolAndLength = tdaList->list.array[gNB_mac->sched_ctrlCommon->time_domain_allocation]->startSymbolAndLength; - int startSymbolIndex, nrOfSymbols; - SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); + int startSymbolIndex = 0; + int nrOfSymbols = 0; + if(gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position == 0) { + startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->time_domain_allocation][1]; + nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->time_domain_allocation][2]; + } else { + startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->time_domain_allocation][1]; + nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->time_domain_allocation][2]; + } if (nrOfSymbols == 2) { gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData = 1; @@ -390,7 +394,6 @@ void schedule_control_sib1(module_id_t module_id, gNB_mac->sched_ctrlCommon->rbSize = rbSize; gNB_mac->sched_ctrlCommon->rbStart = 0; - LOG_D(MAC,"SLIV = %i\n", startSymbolAndLength); LOG_D(MAC,"startSymbolIndex = %i\n", startSymbolIndex); LOG_D(MAC,"nrOfSymbols = %i\n", nrOfSymbols); LOG_D(MAC,"rbSize = %i\n", gNB_mac->sched_ctrlCommon->rbSize); @@ -595,11 +598,15 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) // Configure sched_ctrlCommon for SIB1 schedule_control_sib1(module_idP, CC_id, type0_PDCCH_CSS_config, time_domain_allocation, mcsTableIdx, mcs, candidate_idx, sib1_sdu_length); - // Calculate number of symbols - int startSymbolIndex, nrOfSymbols; - struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; - const int startSymbolAndLength = tdaList->list.array[gNB_mac->sched_ctrlCommon->time_domain_allocation]->startSymbolAndLength; - SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); + int startSymbolIndex = 0; + int nrOfSymbols = 0; + if(gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position == 0) { + startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->time_domain_allocation][1]; + nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->time_domain_allocation][2]; + } else { + startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->time_domain_allocation][1]; + nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->time_domain_allocation][2]; + } // Calculate number of PRB_DMRS uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 9784b6b79e..5f160135df 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -499,7 +499,6 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, ra->rnti, i); - return; } } } diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf index 42b87d5672..feab1d4354 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf @@ -64,13 +64,13 @@ gNBs = #initialULBWPmappingType #0=typeA,1=typeB initialDLBWPmappingType_0 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_0 = 53; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; initialDLBWPk0_1 = 0; initialDLBWPmappingType_1 = 0; - #this is SS=2,L=10 - initialDLBWPstartSymbolAndLength_1 = 81; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; initialDLBWPk0_2 = 0; initialDLBWPmappingType_2 = 0; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 96df4a971f..a91ad7859e 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -64,13 +64,13 @@ gNBs = #initialULBWPmappingType #0=typeA,1=typeB initialDLBWPmappingType_0 = 0; - #this is SS=2,L=12 - initialDLBWPstartSymbolAndLength_0 = 53; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; initialDLBWPk0_1 = 0; initialDLBWPmappingType_1 = 0; - #this is SS=2,L=10 - initialDLBWPstartSymbolAndLength_1 = 81; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; initialDLBWPk0_2 = 0; initialDLBWPmappingType_2 = 0; From 25b8b91020f30bc60576ca36e844bf0fe5e2088c Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 12 Apr 2021 17:01:57 +0200 Subject: [PATCH 039/185] calling dlsch detection in initial sync for sib1 --- executables/nr-ue.c | 2 +- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 10 +- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 44 +++++- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 3 +- openair1/SCHED_NR_UE/defs.h | 14 ++ openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 135 +++++++++--------- openair1/SIMULATION/NR_PHY/pbchsim.c | 2 +- 7 files changed, 130 insertions(+), 80 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 3456a28d7a..57955bfa5f 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -215,7 +215,7 @@ static void UE_synch(void *arg) { double rx_gain_off = 0; nr_get_carrier_frequencies(&UE->frame_parms, &dl_carrier, &ul_carrier); - if (nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa) == 0) { + if (nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa, get_nrUE_params()->nr_dlsch_parallel) == 0) { freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) + round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 35c4a6e8cb..6fb1e75ff3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -720,11 +720,11 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, } void nr_dlsch_deinterleaving(uint8_t symbol, - uint8_t start_symbol, - uint16_t L, - uint16_t *llr, - uint16_t *llr_deint, - uint16_t nb_rb_pdsch) + uint8_t start_symbol, + uint16_t L, + uint16_t *llr, + uint16_t *llr_deint, + uint16_t nb_rb_pdsch) { uint32_t bundle_idx, N_bundle, R, C, r,c; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index a58756b708..8a5fcabdf2 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -202,7 +202,10 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini char duplex_string[2][4] = {"FDD","TDD"}; char prefix_string[2][9] = {"NORMAL","EXTENDED"}; -int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa) +int nr_initial_sync(UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + int n_frames, int sa, + int dlsch_parallel) { int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2, @@ -482,11 +485,12 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, i // if stand alone and sync on ssb do sib1 detection as part of initial sync if (sa==1 && ret==0) { NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; - uint8_t nb_symb_pdcch = pdcch_vars->nb_search_space > 0 ? pdcch_vars->pdcch_config[0].coreset.duration : 0; + int gnb_id = 0; //FIXME int coreset_nb_rb=0; int coreset_start_rb=0; for(int n_ss = 0; n_ssnb_search_space; n_ss++) { + uint8_t nb_symb_pdcch = pdcch_vars->pdcch_config[n_ss].coreset.duration : 0; get_coreset_rballoc(pdcch_vars->pdcch_config[n_ss].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); for (uint16_t l=0; l0){ + NR_UE_DLSCH_t *dlsch = ue->dlsch_SI[gnb_id]; + if (dlsch && (dlsch->active == 1)) { + uint8_t harq_pid = dlsch->current_harq_pid; + NR_DL_UE_HARQ_t *dlsch0_harq = dlsch->harq_processes[harq_pid]; + uint16_t nb_symb_sch = dlsch0_harq->nb_symbols; + uint16_t start_symb_sch = dlsch0_harq->start_symbol; + + for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ + nr_slot_fep_init_sync(ue, + proc, + m, + pdcch_vars->slot, // same slot and offset as pdcch + pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); + } + + int ret = nr_ue_pdsch_procedures(ue, + proc, + gnb_id, + SI_PDSCH, + ue->dlsch_SI[gnb_id], + NULL); + if (ret >= 0) + nr_ue_dlsch_procedures(ue, + proc, + gnb_id, + SI_PDSCH, + ue->dlsch_SI[gnb_id], + NULL, + &ue->dlsch_SI_errors[gnb_id], + dlsch_parallel); + + // deactivate dlsch once dlsch proc is done + ue->dlsch_SI[gnb_id]->active = 0; + } break; } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index af02b4aa36..a258b0a4ba 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1458,7 +1458,8 @@ void generate_RIV_tables(void); int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, int n_frames, - int sa); + int sa, + int dlsch_parallel); /*! \brief This function gets the carrier frequencies either from FP or command-line-set global variables, depending on the availability of the latter diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 52af5f733b..43818a8d50 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -416,6 +416,20 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch0, uint16_t n_pdus); +void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int gNB_id, + PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + int *dlsch_errors, + uint8_t dlsch_parallel); + +int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int eNB_id, PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1); + int nr_ue_pdcch_procedures(uint8_t gNB_id, PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 38f4ec1c02..ae5a3ce1de 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -872,7 +872,7 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, - int eNB_id, + int gNB_id, PDSCH_t pdsch, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1, @@ -892,7 +892,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, fapi_nr_rx_indication_t rx_ind; uint16_t number_pdus = 1; // params for UL time alignment procedure - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[eNB_id]; + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id]; uint8_t is_cw0_active = dlsch0->harq_processes[harq_pid]->status; uint16_t nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; @@ -929,7 +929,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, case RA_PDSCH: case P_PDSCH: case PDSCH: - pdsch_vars = ue->pdsch_vars[proc->thread_id][eNB_id]; + pdsch_vars = ue->pdsch_vars[proc->thread_id][gNB_id]; break; case PMCH: case PDSCH1: @@ -947,8 +947,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, *dlsch_errors=0; if (pdsch == RA_PDSCH) { - if (ue->prach_resources[eNB_id]!=NULL) - dlsch0->rnti = ue->prach_resources[eNB_id]->ra_RNTI; + if (ue->prach_resources[gNB_id]!=NULL) + dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI; else { LOG_E(PHY,"[UE %d] Frame %d, nr_slot_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_slot_rx); //mac_xface->macphy_exit("prach_resources is NULL"); @@ -989,7 +989,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->Nl); LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->harq_processes[harq_pid]->G); LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch0->Kmimo); - LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][eNB_id]->num_pdcch_symbols); + LOG_I(PHY,"start ldpc decode for CW 0 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][gNB_id]->num_pdcch_symbols); #endif #if UE_TIMING_TRACE @@ -1000,7 +1000,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, { ret = nr_dlsch_decoding_mthread(ue, proc, - eNB_id, + gNB_id, pdsch_vars->llr[0], &ue->frame_parms, dlsch0, @@ -1017,7 +1017,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, { ret = nr_dlsch_decoding(ue, proc, - eNB_id, + gNB_id, pdsch_vars->llr[0], &ue->frame_parms, dlsch0, @@ -1057,15 +1057,15 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, dlsch1->harq_processes[harq_pid]->Qm, dlsch1->harq_processes[harq_pid]->Nl); #if UE_TIMING_TRACE - start_meas(&ue->dlsch_unscrambling_stats); + start_meas(&ue->dlsch_unscrambling_stats); #endif - nr_dlsch_unscrambling(pdsch_vars->llr[1], - dlsch1->harq_processes[harq_pid]->G, - 0, - ue->frame_parms.Nid_cell, - dlsch1->rnti); + nr_dlsch_unscrambling(pdsch_vars->llr[1], + dlsch1->harq_processes[harq_pid]->G, + 0, + ue->frame_parms.Nid_cell, + dlsch1->rnti); #if UE_TIMING_TRACE - stop_meas(&ue->dlsch_unscrambling_stats); + stop_meas(&ue->dlsch_unscrambling_stats); #endif #if 0 @@ -1075,69 +1075,66 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Nl %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->Nl); LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> G %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->harq_processes[harq_pid]->G); LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Kmimo %d \n", frame_rx, nr_slot_rx, harq_pid, dlsch1->Kmimo); - LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][eNB_id]->num_pdcch_symbols); + LOG_I(PHY,"start ldpc decode for CW 1 for AbsSubframe %d.%d / %d --> Pdcch Sym %d \n", frame_rx, nr_slot_rx, harq_pid, ue->pdcch_vars[proc->thread_id][gNB_id]->num_pdcch_symbols); #endif #if UE_TIMING_TRACE - start_meas(&ue->dlsch_decoding_stats[proc->thread_id]); + start_meas(&ue->dlsch_decoding_stats[proc->thread_id]); #endif - if(dlsch_parallel) - { - ret1 = nr_dlsch_decoding_mthread(ue, - proc, - eNB_id, - pdsch_vars->llr[1], - &ue->frame_parms, - dlsch1, - dlsch1->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_slot_rx, - harq_pid, - pdsch==PDSCH?1:0, - dlsch1->harq_processes[harq_pid]->TBS>256?1:0); + if(dlsch_parallel) { + ret1 = nr_dlsch_decoding_mthread(ue, + proc, + gNB_id, + pdsch_vars->llr[1], + &ue->frame_parms, + dlsch1, + dlsch1->harq_processes[harq_pid], + frame_rx, + nb_symb_sch, + nr_slot_rx, + harq_pid, + pdsch==PDSCH?1:0, + dlsch1->harq_processes[harq_pid]->TBS>256?1:0); LOG_T(PHY,"CW dlsch decoding is parallelized, ret1 = %d\n", ret1); - } - else - { - ret1 = nr_dlsch_decoding(ue, - proc, - eNB_id, - pdsch_vars->llr[1], - &ue->frame_parms, - dlsch1, - dlsch1->harq_processes[harq_pid], - frame_rx, - nb_symb_sch, - nr_slot_rx, - harq_pid, - pdsch==PDSCH?1:0,//proc->decoder_switch, - dlsch1->harq_processes[harq_pid]->TBS>256?1:0); - LOG_T(PHY,"CWW sequential dlsch decoding, ret1 = %d\n", ret1); - } + } + else { + ret1 = nr_dlsch_decoding(ue, + proc, + gNB_id, + pdsch_vars->llr[1], + &ue->frame_parms, + dlsch1, + dlsch1->harq_processes[harq_pid], + frame_rx, + nb_symb_sch, + nr_slot_rx, + harq_pid, + pdsch==PDSCH?1:0,//proc->decoder_switch, + dlsch1->harq_processes[harq_pid]->TBS>256?1:0); + LOG_T(PHY,"CWW sequential dlsch decoding, ret1 = %d\n", ret1); + } #if UE_TIMING_TRACE - stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); + stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]); #if DISABLE_LOG_X - printf(" --> Unscrambling for CW1 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - printf("AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + printf(" --> Unscrambling for CW1 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + printf("AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); #else - LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", - (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); - LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + LOG_D(PHY, " --> Unscrambling for CW1 %5.3f\n", + (ue->dlsch_unscrambling_stats.p_time)/(cpuf*1000.0)); + LOG_D(PHY, "AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); #endif #endif - LOG_I(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", - frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); + LOG_I(PHY,"AbsSubframe %d.%d --> ldpc Decoding for CW1 %5.3f\n", + frame_rx%1024, nr_slot_rx,(ue->dlsch_decoding_stats[proc->thread_id].p_time)/(cpuf*1000.0)); LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch1->harq_processes[harq_pid]->TBS); } - LOG_D(PHY," ------ end ldpc decoder for AbsSubframe %d.%d ------ \n", frame_rx, nr_slot_rx); LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS); @@ -1145,18 +1142,18 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, switch (pdsch) { case RA_PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, eNB_id, ue, dlsch0, number_pdus); + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, number_pdus); - ue->UE_mode[eNB_id] = RA_RESPONSE; + ue->UE_mode[gNB_id] = RA_RESPONSE; break; case PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, eNB_id, ue, dlsch0, number_pdus); + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, gNB_id, ue, dlsch0, number_pdus); break; case SI_PDSCH: - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, eNB_id, ue, dlsch0, number_pdus); + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, gNB_id, ue, dlsch0, number_pdus); break; default: break; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 746138195e..c244ecfe3a 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -682,7 +682,7 @@ int main(int argc, char **argv) } if (UE->is_synchronized == 0) { UE_nr_rxtx_proc_t proc={0}; - ret = nr_initial_sync(&proc, UE, 1, 0); + ret = nr_initial_sync(&proc, UE, 1, 0, 0); printf("nr_initial_sync1 returns %d\n",ret); if (ret<0) n_errors++; } From 23330e4c67b590e82341eab12a40ba33c8855a53 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 12 Apr 2021 17:21:40 +0200 Subject: [PATCH 040/185] bugfix --- openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 8a5fcabdf2..ba52c11c7e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -490,7 +490,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, int coreset_start_rb=0; for(int n_ss = 0; n_ssnb_search_space; n_ss++) { - uint8_t nb_symb_pdcch = pdcch_vars->pdcch_config[n_ss].coreset.duration : 0; + uint8_t nb_symb_pdcch = pdcch_vars->pdcch_config[n_ss].coreset.duration; get_coreset_rballoc(pdcch_vars->pdcch_config[n_ss].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); for (uint16_t l=0; l Date: Sat, 13 Mar 2021 17:56:23 +0000 Subject: [PATCH 041/185] Remove hard code in nr_pdsch_channel_estimation --- openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 6 +++++- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 1 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) 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 76a48f38ae..909d0b8954 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -657,6 +657,7 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_offset, + bool is_SI, unsigned char Ns, unsigned short p, unsigned char symbol, @@ -694,7 +695,10 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, #endif // generate pilot for gNB port number 1000+p - uint16_t rb_offset = (bwp_start_subcarrier - ue->frame_parms.first_carrier_offset) / 12 - BWPStart; + uint16_t rb_offset = (bwp_start_subcarrier - ue->frame_parms.first_carrier_offset) / 12; + if (is_SI) { + rb_offset -= BWPStart; + } uint8_t config_type = ue->dmrs_DownlinkConfig.pdsch_dmrs_type; int8_t delta = get_delta(p, config_type); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 6c461ef448..1466fabe5d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -70,6 +70,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_offset, + bool is_SI, unsigned char Ns, unsigned short p, unsigned char symbol, diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index ae5a3ce1de..1a72871ca0 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -775,6 +775,7 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_ uint16_t pdsch_nb_rb = dlsch0_harq->nb_rb; uint16_t s0 = dlsch0_harq->start_symbol; uint16_t s1 = dlsch0_harq->nb_symbols; + bool is_SI = dlsch0->rnti_type == _SI_RNTI_; LOG_D(PHY,"[UE %d] PDSCH type %d active in nr_slot_rx %d, harq_pid %d (%d), rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x\n",ue->Mod_id,pdsch,nr_slot_rx,harq_pid,dlsch0->harq_processes[harq_pid]->status,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->harq_processes[harq_pid]->dlDmrsSymbPos); @@ -784,6 +785,7 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_ nr_pdsch_channel_estimation(ue, proc, 0 /*eNB_id*/, + is_SI, nr_slot_rx, aatx /*p*/, m, From 6f31e80ac4eb8de55852eaca569f489aa89d6fa4 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 12 Apr 2021 18:52:05 +0200 Subject: [PATCH 042/185] bugfix for dci reception when sync in second frame --- openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 3 +-- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 1 - openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index ba52c11c7e..ce51924b05 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -498,7 +498,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, proc, l, // the UE PHY has no notion of the symbols to be monitored in the search space pdcch_vars->slot, - pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); + is*fp->samples_per_frame+pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); if (coreset_nb_rb > 0) nr_pdcch_channel_estimation(ue, @@ -549,7 +549,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, break; } } -exit(1); } // exit_fun("debug exit"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 1a72871ca0..5e444173ea 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1141,7 +1141,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS); if(retmax_ldpc_iterations+1){ - switch (pdsch) { case RA_PDSCH: nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index c0d53a3076..8931e3b4fa 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1794,7 +1794,7 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, frame_s = 0; // same frame as ssb slot_s = mac->type0_PDCCH_CSS_config.n_c; } - LOG_I(MAC,"Calling fill_scheduled_response, type0_pdcch, num_pdus %d\n",dl_config->number_pdus); + LOG_D(MAC,"Calling fill_scheduled_response, type0_pdcch, num_pdus %d\n",dl_config->number_pdus); fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, module_idP, cc_id, frame_s, slot_s, 0); // TODO fix thread_id, for now assumed 0 } } From 047b7b17ba942ad4aecc01832b159ea4c7959cf1 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 13 Apr 2021 02:31:40 +0530 Subject: [PATCH 043/185] Uplink indication --- nfapi/oai_integration/nfapi_pnf.c | 33 + .../nfapi/public_inc/nfapi_nr_interface_scf.h | 7 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 840 ++++++++++++++---- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 72 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 136 ++- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 60 +- 6 files changed, 937 insertions(+), 211 deletions(-) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index e744fcbb24..92057186e2 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -2406,3 +2406,36 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //free(ind.rx_indication_body.rx_pdu_list); return retval; } + +//NR UPLINK INDICATION + +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; + return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; + return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION; + return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; + return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION; + return nfapi_pnf_p7_nr_rach_ind(p7_config_g, ind); +} + diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index bc5e7af45f..85f1efa3f4 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -1516,10 +1516,11 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_of_pdus; - nfapi_nr_rx_data_pdu_t* pdu_list; + nfapi_nr_rx_data_pdu_t *pdu_list; //changed from pointer to struct - gokul } nfapi_nr_rx_data_indication_t; @@ -1542,6 +1543,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_crcs; @@ -1679,6 +1681,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t num_ucis; @@ -1715,6 +1718,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; @@ -1747,6 +1751,7 @@ typedef struct{ typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 49ecba5eac..a97e4ccaaf 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -3354,6 +3354,308 @@ static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_ } +//NR UPLINK indication function packing + +//RX DATA INDICATION + +static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push16(value->pdu_length, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + + +static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rx_data_indication_body(pNfapiMsg->pdu_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t pack_nr_crc_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push8(value->tb_crc_status, ppWritePackedMsg, end) && + push16(value->num_cb, ppWritePackedMsg, end) && + //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + +static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!pack_nr_crc_indication_body(pNfapiMsg->crc_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t pack_nr_srs_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push8(value->num_symbols, ppWritePackedMsg, end) && + push8(value->wide_band_snr, ppWritePackedMsg, end) && + push8(value->num_reported_symbols, ppWritePackedMsg, end) && + push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(push8(value->reported_symbol_list->rb_list->rb_snr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//RACH INDICATION + +static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) && + push8(value->symbol_index, ppWritePackedMsg, end) && + push8(value->slot_index, ppWritePackedMsg, end) && + push8(value->freq_index, ppWritePackedMsg, end) && + push8(value->avg_rssi, ppWritePackedMsg, end) && + push8(value->avg_snr, ppWritePackedMsg, end) && + push8(value->num_preamble, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(push8(value->preamble_list->preamble_index, ppWritePackedMsg, end) && + push16(value->preamble_list->timing_advance, ppWritePackedMsg, end) && + push32(value->preamble_list->preamble_pwr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + +//UCI INDICATION + +static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr->sr_indication, ppWritePackedMsg, end) && + push8(value->sr->sr_confidence_level, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq->num_harq, ppWritePackedMsg, end) && + push8(value->harq->harq_confidence_level, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iharq->num_harq;i++) + { + if(!(push8(value->harq->harq_list[i].harq_value, ppWritePackedMsg, end) + )) + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr.sr_bit_len, ppWritePackedMsg, end) && + pusharray8(value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq.harq_crc, ppWritePackedMsg, end) && + push8(value->harq.harq_bit_len, ppWritePackedMsg, end) && + pusharray8(value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end) && + push8(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end) && + push8(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(push16(value->pdu_type, ppWritePackedMsg, end) && + push16(value->pdu_size, ppWritePackedMsg, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} // Main pack function - public @@ -3419,49 +3721,24 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: @@ -3577,7 +3854,6 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu switch (pMessageHeader->message_id) { case NFAPI_DL_CONFIG_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -3585,7 +3861,6 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_TX_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_HI_DCI0_REQUEST: @@ -3609,7 +3884,6 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu break; case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -6074,6 +6348,334 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * return 1; } + +//UNPACK NR UPLINK INDICATION FUNCTIONS + +//RX DATA INDICATION + +static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull16(ppReadPackedMsg, &value->pdu_length, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + return 1; +} + + +static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + // uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message rx data indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + printf("\n"); + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull8(ppReadPackedMsg, &value->tb_crc_status, end) && + pull16(ppReadPackedMsg, &value->num_cb, end) && + //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + + return 1; +} + +static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t unpack_nr_srs_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->num_symbols, end) && + pull8(ppReadPackedMsg, &value->wide_band_snr, end) && + pull8(ppReadPackedMsg, &value->num_reported_symbols, end) && + pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list->rb_snr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR RACH + +static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && + pull8(ppReadPackedMsg, &value->symbol_index, end) && + pull8(ppReadPackedMsg, &value->slot_index, end) && + pull8(ppReadPackedMsg, &value->freq_index, end) && + pull8(ppReadPackedMsg, &value->avg_rssi, end) && + pull8(ppReadPackedMsg, &value->avg_snr, end) && + pull8(ppReadPackedMsg, &value->num_preamble, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && + pull16(ppReadPackedMsg, &value->preamble_list->timing_advance, end) && + pull32(ppReadPackedMsg, &value->preamble_list->preamble_pwr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { + + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; i< pNfapiMsg->number_of_pdus;i++) + { + if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR UCI + +static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + uint8_t *ptr = *ppReadPackedMsg; + printf("\n Read P7 message uci_0_1 indication unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && + pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) + )) + return 0; + } + + // if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + // uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value + // temp = (uint8_t*) malloc(sizeof(uint8_t)); + // //printf("value->harq->num_harq = %d \n", value->harq->num_harq); + // // if(!(pull8(ppReadPackedMsg, temp, end) && + // // pull8(ppReadPackedMsg, temp, end) + // // )) + // // return 0; + + // // for(int i=0; i<1;i++) + // // { + // // if(!(pull8(ppReadPackedMsg, temp, end) //review - gokul + // // )) + // // return 0; + // // } + // } + + return 1; +} + + +static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) && + pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) && + pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) && + pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) && + pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) && + pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) && + pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) && + pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) + )) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && + pull16(ppReadPackedMsg, &value->pdu_size, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; + unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + + static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { uint8_t proceed = 1; @@ -7699,62 +8301,32 @@ static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBuf if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) retLen = sizeof(nfapi_nr_tx_data_request_t); break; - - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) + retLen = sizeof(nfapi_nr_rx_data_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) + retLen = sizeof(nfapi_nr_crc_indication_t); break; - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) + retLen = sizeof(nfapi_nr_rach_indication_t); break; - - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) + retLen = sizeof(nfapi_nr_uci_indication_t); break; - - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) + retLen = sizeof(nfapi_nr_srs_indication_t); break; - - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; - - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; - - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; - - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) retLen = sizeof(nfapi_nr_dl_node_sync_t); @@ -8064,15 +8636,15 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); return -1; } - /* - uint8_t *ptr = pMessageBuf; - printf("\n Read P7 message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); -*/ + + // uint8_t *ptr = pMessageBuf; + // printf("\n Read P7 message unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); @@ -8138,83 +8710,41 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * return -1; break; - case NFAPI_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) + result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); else return -1; break; - case NFAPI_RX_ULSCH_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) + result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) + result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) + result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_RX_SR_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_CQI_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_INDICATION: - if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index efcb60ce96..88aa1391cb 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -175,17 +175,7 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t pnf_p7_t* _this = (pnf_p7_t*)(config); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); } -int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) -{ - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); -} int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) { if(config == NULL || ind == NULL) @@ -265,3 +255,65 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } + +//NR UPLINK INDICATION + +int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); +} + +int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); +} + +int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); +} + +int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); +} + +int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); +} diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 8edb168e38..453f0f3769 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -1455,6 +1455,102 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } +//NR HANDLES FOR UPLINK MESSAGES + +void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_rx_data_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_crc_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_srs_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_uci_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + } +} + +void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_rach_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { //printf("received UL Node sync"); @@ -2035,46 +2131,26 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_HARQ_INDICATION: - vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_CRC_INDICATION: - vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + vnf_handle_nr_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RX_ULSCH_INDICATION: - vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + vnf_handle_nr_uci_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RACH_INDICATION: - vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_SRS_INDICATION: - vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RX_SR_INDICATION: - vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_RX_CQI_INDICATION: - vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_LBT_DL_INDICATION: - vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_NB_HARQ_INDICATION: - vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_NRACH_INDICATION: - vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - case NFAPI_UE_RELEASE_RESPONSE: vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7); break; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 9c118ec53b..2e0abda556 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -54,7 +54,14 @@ extern uint16_t sf_ahead; extern uint16_t sl_ahead; void handle_nr_rach(NR_UL_IND_t *UL_info) { - + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->rach_ind.number_of_pdus>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_rach_indication(&UL_info->rach_ind); + UL_info->rach_ind.number_of_pdus = 0; + } + } + else { if (UL_info->rach_ind.number_of_pdus>0) { LOG_I(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); int npdus = UL_info->rach_ind.number_of_pdus; @@ -75,10 +82,19 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } } } +} void handle_nr_uci(NR_UL_IND_t *UL_info) -{ +{ + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->uci_ind.num_ucis>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + //oai_nfapi_nr_uci_indication(&UL_info->uci_ind); + UL_info->uci_ind.num_ucis = 0; + } + } + else { const module_id_t mod_id = UL_info->module_id; const frame_t frame = UL_info->frame; const sub_frame_t slot = UL_info->slot; @@ -110,10 +126,24 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; } - +} void handle_nr_ulsch(NR_UL_IND_t *UL_info) -{ +{ + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->crc_ind.number_crcs>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_crc_indication(&UL_info->crc_ind); + UL_info->crc_ind.number_crcs = 0; + } + + if (UL_info->rx_ind.number_of_pdus>0) { + //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); + oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); + UL_info->rx_ind.number_of_pdus = 0; + } + } + else { if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { @@ -139,17 +169,16 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - //Gokul - // nr_rx_sdu(UL_info->module_id, - // UL_info->CC_id, - // UL_info->rx_ind.sfn, - // UL_info->rx_ind.slot, - // rx->rnti, - // crc->tb_crc_status ? NULL : rx->pdu, - // rx->pdu_length, - // rx->timing_advance, - // rx->ul_cqi, - // rx->rssi); + nr_rx_sdu(UL_info->module_id, + UL_info->CC_id, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + rx->rnti, + crc->tb_crc_status ? NULL : rx->pdu, + rx->pdu_length, + rx->timing_advance, + rx->ul_cqi, + rx->rssi); //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) @@ -169,6 +198,7 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) UL_info->crc_ind.number_crcs, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); + } } } From f5b2da21b233d876e7732a642f0210672d35462e Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 31 Mar 2021 11:41:11 +0200 Subject: [PATCH 044/185] fixing previous commit --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 8 +++++--- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index d4e5e9c2c2..3145a398fa 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3028,18 +3028,20 @@ int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slot, lte_frame_type int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols,int startSymbol) { int l0; - int ld = NrOfSymbols; + int ld = NrOfSymbols+startSymbol; if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2) l0=2; else if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3) l0=3; else AssertFatal(1==0,"Illegal dmrs_TypeA_Position %d\n",(int)dmrs_TypeA_Position); if (pdsch_Config == NULL) { // Initial BWP - return(1<dmrs_DownlinkForPDSCH_MappingTypeA && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup) { // Relative to start of slot - ld += startSymbol; NR_DMRS_DownlinkConfig_t *dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; AssertFatal(NrOfSymbols>1 && NrOfSymbols < 15,"Illegal NrOfSymbols %d\n",NrOfSymbols); int pos2=0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index b10faddfbb..97486cd393 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -610,8 +610,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) // Calculate number of PRB_DMRS uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6; - uint16_t dlDmrsSymbPos = fill_dmrs_mask(gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, - gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, startSymbolIndex, nrOfSymbols); + uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, startSymbolIndex, nrOfSymbols); uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos); const uint32_t TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), From 6c7280c087af7f8042f8202ea624b722722d5582 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Thu, 25 Feb 2021 10:56:08 +0000 Subject: [PATCH 045/185] Define Initial BWP with the same locationAndBandwidth as Coreset0 defined by PDCCHConfigSIB1 in MIB --- .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index a91ad7859e..9b9e742456 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -50,8 +50,8 @@ gNBs = dl_carrierBandwidth = 106; #initialDownlinkBWP #genericParameters - # this is RBstart=41,L=24 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 6368; + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 12952; # 6366 12925 12956 28875 12952 # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 1; @@ -94,7 +94,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 6368; + initialULBWPlocationAndBandwidth = 12952; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 1; From e030713c0953c972f14dc7c4a8255d944029103d Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 13 Apr 2021 10:37:04 +0200 Subject: [PATCH 046/185] fix dlsch decoding for sib1 --- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 3 ++- openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 3 ++- openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 3 +-- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 1 - openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 6 ++---- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index b441635246..ca696f690d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -288,7 +288,8 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); - LOG_D(PHY,"dlsch coding A %d G %d mod_order %d\n", A,G, mod_order); + LOG_D(PHY,"DLSCH coding, A %d (%d) G %d nb_re_dmrs %d length_dmrs %d Nl %d nb_symb_sch %d nb_rb %d\n", + A,A/8,G,nb_re_dmrs,length_dmrs,rel15->nrOfLayers,nb_symb_sch,nb_rb); if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index d5c0245fdc..e2ccc81871 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -354,7 +354,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, dmrs_length, harq_process->Qm,harq_process->Nl); G = harq_process->G; - LOG_D(PHY,"DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,A/8,G, nb_re_dmrs,harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); + LOG_D(PHY,"DLSCH Decoding, harq_pid %d TBS %d (%d) G %d nb_re_dmrs %d length dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n", + harq_pid,A,A/8,G, nb_re_dmrs, dmrs_length, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); if ((harq_process->R)<1024) Coderate = (float) (harq_process->R) /(float) 1024; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index ce51924b05..00542322b0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -524,7 +524,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, proc, m, pdcch_vars->slot, // same slot and offset as pdcch - pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); + is*fp->samples_per_frame+pdcch_vars->sfn*fp->samples_per_frame+ue->rx_offset); } int ret = nr_ue_pdsch_procedures(ue, @@ -546,7 +546,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, // deactivate dlsch once dlsch proc is done ue->dlsch_SI[gnb_id]->active = 0; } - break; } } } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 5e444173ea..9944e9938b 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1145,7 +1145,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, case RA_PDSCH: nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, gNB_id, ue, dlsch0, number_pdus); - ue->UE_mode[gNB_id] = RA_RESPONSE; break; case PDSCH: diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 97486cd393..479b7ed549 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -336,8 +336,6 @@ void schedule_control_sib1(module_id_t module_id, fill_coresetZero(gNB_mac->sched_ctrlCommon->coreset,type0_PDCCH_CSS_config); fill_default_initialDownlinkBWP(gNB_mac->sched_ctrlCommon->active_bwp,servingcellconfigcommon); } - gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL; - gNB_mac->sched_ctrlCommon->time_domain_allocation = time_domain_allocation; gNB_mac->sched_ctrlCommon->mcsTableIdx = mcsTableIdx; gNB_mac->sched_ctrlCommon->mcs = mcs; @@ -377,7 +375,7 @@ void schedule_control_sib1(module_id_t module_id, // Calculate number of PRB_DMRS uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6; - uint16_t dlDmrsSymbPos = fill_dmrs_mask(gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, + uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, nrOfSymbols, startSymbolIndex); uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos); @@ -482,7 +480,7 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; - pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup, scc->dmrs_TypeA_Position, pdsch_pdu_rel15->NrOfSymbols, pdsch_pdu_rel15->StartSymbolIndex); + pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, pdsch_pdu_rel15->NrOfSymbols, pdsch_pdu_rel15->StartSymbolIndex); LOG_D(MAC,"dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos); From 7e5ef00996e6f7c8e575f7b9e550ce2bafd10f14 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 13 Apr 2021 16:12:06 +0200 Subject: [PATCH 047/185] removal of bwp from sib1, removal of fill_default_initialDownlinkBWP --- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 19 +-- openair1/SCHED_NR_UE/defs.h | 16 +-- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 37 +++--- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 3 + openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 6 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 29 ++--- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 109 +++++++++--------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 +- openair2/RRC/NR/nr_rrc_proto.h | 2 - openair2/RRC/NR/rrc_gNB_reconfig.c | 25 ---- 13 files changed, 116 insertions(+), 139 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 00542322b0..c73d2356a0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -484,6 +484,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, // if stand alone and sync on ssb do sib1 detection as part of initial sync if (sa==1 && ret==0) { + bool dec = false; NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; int gnb_id = 0; //FIXME int coreset_nb_rb=0; @@ -534,20 +535,22 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, ue->dlsch_SI[gnb_id], NULL); if (ret >= 0) - nr_ue_dlsch_procedures(ue, - proc, - gnb_id, - SI_PDSCH, - ue->dlsch_SI[gnb_id], - NULL, - &ue->dlsch_SI_errors[gnb_id], - dlsch_parallel); + dec = nr_ue_dlsch_procedures(ue, + proc, + gnb_id, + SI_PDSCH, + ue->dlsch_SI[gnb_id], + NULL, + &ue->dlsch_SI_errors[gnb_id], + dlsch_parallel); // deactivate dlsch once dlsch proc is done ue->dlsch_SI[gnb_id]->active = 0; } } } + if (dec == false) // sib1 not decoded + ret = -1; } // exit_fun("debug exit"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT); diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 43818a8d50..046b79efdc 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -416,14 +416,14 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch0, uint16_t n_pdus); -void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - int gNB_id, - PDSCH_t pdsch, - NR_UE_DLSCH_t *dlsch0, - NR_UE_DLSCH_t *dlsch1, - int *dlsch_errors, - uint8_t dlsch_parallel); +bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int gNB_id, + PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + int *dlsch_errors, + uint8_t dlsch_parallel); int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 9944e9938b..afcfa25d7a 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -872,18 +872,18 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_ return 0; } -void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - int gNB_id, - PDSCH_t pdsch, - NR_UE_DLSCH_t *dlsch0, - NR_UE_DLSCH_t *dlsch1, - int *dlsch_errors, - uint8_t dlsch_parallel) { +bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int gNB_id, + PDSCH_t pdsch, + NR_UE_DLSCH_t *dlsch0, + NR_UE_DLSCH_t *dlsch1, + int *dlsch_errors, + uint8_t dlsch_parallel) { if (dlsch0==NULL) AssertFatal(0,"dlsch0 should be defined at this level \n"); - + bool dec = false; int harq_pid = dlsch0->current_harq_pid; int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; @@ -937,11 +937,11 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, case PDSCH1: LOG_E(PHY,"Illegal PDSCH %d for ue_pdsch_procedures\n",pdsch); pdsch_vars = NULL; - return; + return false; break; default: pdsch_vars = NULL; - return; + return false; break; } @@ -950,17 +950,17 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, if (pdsch == RA_PDSCH) { if (ue->prach_resources[gNB_id]!=NULL) - dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI; + dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI; else { - LOG_E(PHY,"[UE %d] Frame %d, nr_slot_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_slot_rx); - //mac_xface->macphy_exit("prach_resources is NULL"); - return; + LOG_E(PHY,"[UE %d] Frame %d, nr_slot_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_slot_rx); + //mac_xface->macphy_exit("prach_resources is NULL"); + return false; } } // exit dlsch procedures as there are no active dlsch if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) - return; + return false; // start ldpc decode for CW 0 dlsch0->harq_processes[harq_pid]->G = nr_get_G(dlsch0->harq_processes[harq_pid]->nb_rb, @@ -1141,6 +1141,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS); if(retmax_ldpc_iterations+1){ + dec = true; switch (pdsch) { case RA_PDSCH: nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); @@ -1248,10 +1249,12 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } // reset TA flag ul_time_alignment->apply_ta = 0; - LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); + LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", + frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); } } } + return dec; } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 43e2d29b97..d18bd66593 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -38,6 +38,8 @@ #include #include +#include "NR_SubcarrierSpacing.h" + #define TABLE_38213_13_1_NUM_INDEXES 15 #define TABLE_38213_13_2_NUM_INDEXES 14 #define TABLE_38213_13_3_NUM_INDEXES 9 @@ -456,6 +458,7 @@ typedef struct Type0_PDCCH_CSS_config_s { uint32_t ssb_length; uint32_t ssb_index; uint32_t cset_start_rb; + NR_SubcarrierSpacing_t scs_pdcch; bool active; } NR_Type0_PDCCH_CSS_config_t; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 3145a398fa..6bce46ba36 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3286,7 +3286,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD else scs_pdcch = NR_SubcarrierSpacing_kHz30; } - + type0_PDCCH_CSS_config->scs_pdcch = scs_pdcch; type0_PDCCH_CSS_config->ssb_index = ssb_index; type0_PDCCH_CSS_config->frame = frameP; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 186fe34e81..c5df3418bf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -852,8 +852,8 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra { int mcsIndex; int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0; - gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; - NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; + gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_SearchSpace_t *ss = ra->ra_ss; // This code from this point on will not work on initialBWP or CORESET0 @@ -936,7 +936,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(pdcch_pdu_rel15, ss, coreset, scc, bwp); + nr_configure_pdcch(nr_mac,pdcch_pdu_rel15, ss, coreset, scc, bwp); nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu_rel15; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 479b7ed549..5ea83c6ac6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -319,7 +319,6 @@ void schedule_control_sib1(module_id_t module_id, int num_total_bytes) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; - NR_ServingCellConfigCommon_t *servingcellconfigcommon = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; int ret; @@ -327,14 +326,12 @@ void schedule_control_sib1(module_id_t module_id, gNB_mac->sched_ctrlCommon = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon)); gNB_mac->sched_ctrlCommon->search_space = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->search_space)); gNB_mac->sched_ctrlCommon->coreset = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->coreset)); - gNB_mac->sched_ctrlCommon->active_bwp = calloc(1,sizeof(*gNB_mac->sched_ctrlCommon->active_bwp)); for (int i=0; i<3; i++){ // loop over possible aggregation levels ret = fill_searchSpaceZero(gNB_mac->sched_ctrlCommon->search_space,type0_PDCCH_CSS_config,4<sched_ctrlCommon->coreset,type0_PDCCH_CSS_config); - fill_default_initialDownlinkBWP(gNB_mac->sched_ctrlCommon->active_bwp,servingcellconfigcommon); } gNB_mac->sched_ctrlCommon->time_domain_allocation = time_domain_allocation; gNB_mac->sched_ctrlCommon->mcsTableIdx = mcsTableIdx; @@ -345,7 +342,7 @@ void schedule_control_sib1(module_id_t module_id, find_aggregation_candidates(&gNB_mac->sched_ctrlCommon->aggregation_level, &nr_of_candidates, gNB_mac->sched_ctrlCommon->search_space); gNB_mac->sched_ctrlCommon->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], - gNB_mac->sched_ctrlCommon->active_bwp, + NULL, gNB_mac->sched_ctrlCommon->coreset, gNB_mac->sched_ctrlCommon->aggregation_level, 0, @@ -414,7 +411,6 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, NR_COMMON_channels_t *cc = gNB_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_CellGroupConfig_t *secondaryCellGroup = gNB_mac->secondaryCellGroupCommon; - NR_BWP_Downlink_t *bwp = gNB_mac->sched_ctrlCommon->active_bwp; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); @@ -422,15 +418,12 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(pdcch_pdu_rel15, + nr_configure_pdcch(gNB_mac, + pdcch_pdu_rel15, gNB_mac->sched_ctrlCommon->search_space, gNB_mac->sched_ctrlCommon->coreset, scc, - bwp); - - // TODO: This assignment should be done in function nr_configure_pdcch() - pdcch_pdu_rel15->BWPSize = gNB_mac->type0_PDCCH_CSS_config->num_rbs; - pdcch_pdu_rel15->BWPStart = gNB_mac->type0_PDCCH_CSS_config->cset_start_rb; + NULL); nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); @@ -448,12 +441,8 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, pdsch_pdu_rel15->BWPSize = type0_PDCCH_CSS_config->num_rbs; pdsch_pdu_rel15->BWPStart = type0_PDCCH_CSS_config->cset_start_rb; - pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; - if (bwp->bwp_Common->genericParameters.cyclicPrefix) { - pdsch_pdu_rel15->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix; - } else { - pdsch_pdu_rel15->CyclicPrefix = 0; - } + pdsch_pdu_rel15->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch; + pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs,0); @@ -465,7 +454,7 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, pdsch_pdu_rel15->nrOfLayers = 1; pdsch_pdu_rel15->transmissionScheme = 0; pdsch_pdu_rel15->refPoint = 1; - pdsch_pdu_rel15->dmrsConfigType = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + pdsch_pdu_rel15->dmrsConfigType = 0; pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; pdsch_pdu_rel15->SCID = 0; pdsch_pdu_rel15->numDmrsCdmGrpsNoData = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData; @@ -499,7 +488,7 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, dci_pdu_rel15_t dci_payload; memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t)); - dci_payload.bwp_indicator.val = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id; + dci_payload.bwp_indicator.val = 0; // frequency domain assignment dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0( @@ -527,7 +516,7 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, dci_format, rnti_type, pdsch_pdu_rel15->BWPSize, - gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id); + 0); LOG_D(MAC,"BWPSize: %i\n", pdcch_pdu_rel15->BWPSize); LOG_D(MAC,"BWPStart: %i\n", pdcch_pdu_rel15->BWPStart); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 296b271df5..52d57b2eb2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -780,7 +780,7 @@ void nr_schedule_ue_spec(module_id_t module_id, dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, bwp); + nr_configure_pdcch(gNB_mac,pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, bwp); gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 7c49c17ee6..ba575e968b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -175,7 +175,7 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac, int coreset_id = coreset->controlResourceSetId; int *cce_list; - if(bwp->bwp_Id == 0) { + if(bwp == NULL || bwp->bwp_Id == 0) { cce_list = nr_mac->cce_list[1][0]; } else { cce_list = nr_mac->cce_list[bwp->bwp_Id][coreset_id]; @@ -554,70 +554,75 @@ void config_uldci(const NR_BWP_Uplink_t *ubwp, dci_pdu_rel15->rv); } -void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, +void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, NR_ServingCellConfigCommon_t *scc, NR_BWP_Downlink_t *bwp) { - if (bwp) { // This is not the InitialBWP + int sps; + if (bwp) { // This is not for SIB1 pdcch_pdu->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); pdcch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); pdcch_pdu->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; pdcch_pdu->CyclicPrefix = (bwp->bwp_Common->genericParameters.cyclicPrefix==NULL) ? 0 : *bwp->bwp_Common->genericParameters.cyclicPrefix; - // first symbol //AssertFatal(pdcch_scs==kHz15, "PDCCH SCS above 15kHz not allowed if a symbol above 2 is monitored"); - int sps = bwp->bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; - - AssertFatal(ss->monitoringSymbolsWithinSlot!=NULL,"ss->monitoringSymbolsWithinSlot is null\n"); - AssertFatal(ss->monitoringSymbolsWithinSlot->buf!=NULL,"ss->monitoringSymbolsWithinSlot->buf is null\n"); - - // for SPS=14 8 MSBs in positions 13 downto 6 - uint16_t monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | - (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - - for (int i=0; i>(sps-1-i))&1) { - pdcch_pdu->StartSymbolIndex=i; - break; - } - } - - pdcch_pdu->DurationSymbols = coreset->duration; - - for (int i=0;i<6;i++) - pdcch_pdu->FreqDomainResource[i] = coreset->frequencyDomainResources.buf[i]; - - - //cce-REG-MappingType - pdcch_pdu->CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved? - NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED : NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED; - - if (pdcch_pdu->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { - pdcch_pdu->RegBundleSize = (coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize); - pdcch_pdu->InterleaverSize = (coreset->cce_REG_MappingType.choice.interleaved->interleaverSize==NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->interleaverSize); - AssertFatal(scc->physCellId != NULL,"scc->physCellId is null\n"); - pdcch_pdu->ShiftIndex = coreset->cce_REG_MappingType.choice.interleaved->shiftIndex != NULL ? *coreset->cce_REG_MappingType.choice.interleaved->shiftIndex : *scc->physCellId; - } - else { - pdcch_pdu->RegBundleSize = 0; - pdcch_pdu->InterleaverSize = 0; - pdcch_pdu->ShiftIndex = 0; - } - - if(coreset->controlResourceSetId == 0) { - pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; - } else{ - pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; - } - - //precoderGranularity - pdcch_pdu->precoderGranularity = coreset->precoderGranularity; + sps = bwp->bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; } - else { // this is for InitialBWP - AssertFatal(1==0,"Fill in InitialBWP PDCCH configuration\n"); + else { + pdcch_pdu->BWPSize = gNB_mac->type0_PDCCH_CSS_config->num_rbs; + pdcch_pdu->BWPStart = gNB_mac->type0_PDCCH_CSS_config->cset_start_rb; + pdcch_pdu->SubcarrierSpacing = gNB_mac->type0_PDCCH_CSS_config->scs_pdcch; + pdcch_pdu->CyclicPrefix = 0; + sps = 14; } + + AssertFatal(ss->monitoringSymbolsWithinSlot!=NULL,"ss->monitoringSymbolsWithinSlot is null\n"); + AssertFatal(ss->monitoringSymbolsWithinSlot->buf!=NULL,"ss->monitoringSymbolsWithinSlot->buf is null\n"); + + // for SPS=14 8 MSBs in positions 13 downto 6 + uint16_t monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | + (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + + for (int i=0; i>(sps-1-i))&1) { + pdcch_pdu->StartSymbolIndex=i; + break; + } + } + + pdcch_pdu->DurationSymbols = coreset->duration; + + for (int i=0;i<6;i++) + pdcch_pdu->FreqDomainResource[i] = coreset->frequencyDomainResources.buf[i]; + + + //cce-REG-MappingType + pdcch_pdu->CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved? + NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED : NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED; + + if (pdcch_pdu->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { + pdcch_pdu->RegBundleSize = (coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize); + pdcch_pdu->InterleaverSize = (coreset->cce_REG_MappingType.choice.interleaved->interleaverSize==NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->interleaverSize); + AssertFatal(scc->physCellId != NULL,"scc->physCellId is null\n"); + pdcch_pdu->ShiftIndex = coreset->cce_REG_MappingType.choice.interleaved->shiftIndex != NULL ? *coreset->cce_REG_MappingType.choice.interleaved->shiftIndex : *scc->physCellId; + } + else { + pdcch_pdu->RegBundleSize = 0; + pdcch_pdu->InterleaverSize = 0; + pdcch_pdu->ShiftIndex = 0; + } + + if(coreset->controlResourceSetId == 0) { + pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; + } else{ + pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; + } + + //precoderGranularity + pdcch_pdu->precoderGranularity = coreset->precoderGranularity; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 5f160135df..8dbee80427 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1090,7 +1090,7 @@ void nr_schedule_ulsch(module_id_t module_id, ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; ul_dci_req->numPdus += 1; - nr_configure_pdcch(pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, sched_ctrl->active_bwp); + nr_configure_pdcch(RC.nrmac[module_id], pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, sched_ctrl->active_bwp); pdcch_pdu_bwp_coreset[bwpid][coresetid] = pdcch_pdu; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index f552b6c606..2f08d909d8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -241,7 +241,8 @@ void find_search_space(int ss_type, NR_BWP_Downlink_t *bwp, NR_SearchSpace_t *ss); -void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, +void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, NR_ServingCellConfigCommon_t *scc, diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 69b8481286..1c9e7a6d41 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -72,8 +72,6 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); -void fill_default_initialDownlinkBWP(NR_BWP_Downlink_t *bwp, NR_ServingCellConfigCommon_t *servingcellconfigcommon); - void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_ServingCellConfig_t *servingcellconfigdedicated, NR_CellGroupConfig_t *secondaryCellGroup, diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index efe18494df..aabdd61fa7 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -49,31 +49,6 @@ #define false 0 #define true 1 -void fill_default_initialDownlinkBWP(NR_BWP_Downlink_t *bwp, NR_ServingCellConfigCommon_t *servingcellconfigcommon) { - - bwp->bwp_Id = 0; - - bwp->bwp_Common=calloc(1,sizeof(*bwp->bwp_Common)); - memcpy((void*)&bwp->bwp_Common, - &servingcellconfigcommon->downlinkConfigCommon->initialDownlinkBWP, - sizeof(bwp->bwp_Common)); - - bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated)); - bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config)); - bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; - bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup)); - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID0=NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID1=NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); - *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0; -} void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_ServingCellConfig_t *servingcellconfigdedicated, From 0fac0ee70c5928afb98c3fa1e13f1586b938f4ae Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 14 Apr 2021 15:03:25 +0200 Subject: [PATCH 048/185] filling config request, adjustment of prach functions and remove hardcoding from sib1 --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 4 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 2 +- openair2/LAYER2/NR_MAC_UE/config_ue.c | 199 ++++++++++++++++-- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 + openair2/LAYER2/NR_MAC_UE/mac_proto.h | 4 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 1 + openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 152 +++++++------ openair2/RRC/NR/MESSAGES/asn1_msg.c | 9 +- openair2/RRC/NR_UE/rrc_UE.c | 14 +- openair2/RRC/NR_UE/rrc_defs.h | 1 + 13 files changed, 304 insertions(+), 90 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 0a7ae96e09..6bce39f792 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -866,7 +866,7 @@ int main(int argc, char **argv) rrc.carrier.MIB = (uint8_t*) malloc(4); rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0); - nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,secondaryCellGroup); + nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,NULL,secondaryCellGroup); nr_dcireq_t dcireq; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index fce690ebd2..c732426863 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -726,7 +726,7 @@ int main(int argc, char **argv) rrc.carrier.MIB = (uint8_t*) malloc(4); rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0); - nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,secondaryCellGroup); + nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib,NULL,secondaryCellGroup); nr_ue_phy_config_request(&UE_mac->phy_config); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 6bce46ba36..7531bdcfce 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1179,12 +1179,12 @@ int get_format0(uint8_t index, return format; } -int64_t *get_prach_config_info(uint32_t pointa, +int64_t *get_prach_config_info(frequency_range_t freq_range, uint8_t index, uint8_t unpaired) { int64_t *prach_config_info_p; - if (pointa > 2016666) { //FR2 + if (freq_range == FR2) { //FR2 prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index]; } else { // FR1 diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 0523015712..ddb80dbd45 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -113,7 +113,7 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPreco int get_format0(uint8_t index, uint8_t unpaired,frequency_range_t); -int64_t *get_prach_config_info(uint32_t pointa, +int64_t *get_prach_config_info(frequency_range_t freq_range, uint8_t index, uint8_t unpaired); diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 47b0908d3f..9797db6168 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -34,6 +34,8 @@ #include "NR_MAC_UE/mac_proto.h" #include "NR_MAC-CellGroupConfig.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" +#include "common/utils/nr/nr_common.h" +#include "executables/softmodem-common.h" int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, @@ -141,9 +143,167 @@ int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, } +void config_common_ue_sa(NR_UE_MAC_INST_t *mac, + module_id_t module_id, + int cc_idP) { + + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + NR_ServingCellConfigCommonSIB_t *scc = mac->scc_SIB; + + mac->phy_config.Mod_id = module_id; + mac->phy_config.CC_id = cc_idP; + + LOG_D(MAC, "Entering SA UE Config Common\n"); + + // carrier config + cfg->carrier_config.dl_bandwidth = config_bandwidth(scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + *scc->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR); + + uint64_t dl_bw_khz = (12*scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth)* + (15<downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing); + cfg->carrier_config.dl_frequency = (downlink_frequency[cc_idP][0]/1000) - (dl_bw_khz>>1); + + for (int i=0; i<5; i++) { + if (i==scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { + cfg->carrier_config.dl_grid_size[i] = scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + cfg->carrier_config.dl_k0[i] = scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->offsetToCarrier; + } + else { + cfg->carrier_config.dl_grid_size[i] = 0; + cfg->carrier_config.dl_k0[i] = 0; + } + } + + cfg->carrier_config.uplink_bandwidth = config_bandwidth(scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth, + scc->uplinkConfigCommon->frequencyInfoUL.frequencyBandList==NULL ? + *scc->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR : + *scc->uplinkConfigCommon->frequencyInfoUL.frequencyBandList->list.array[0]->freqBandIndicatorNR); + + + if (scc->uplinkConfigCommon->frequencyInfoUL.absoluteFrequencyPointA == NULL) + cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency; + else + // TODO check if corresponds to what reported in SIB1 + cfg->carrier_config.uplink_frequency = (downlink_frequency[cc_idP][0]/1000) + uplink_frequency_offset[cc_idP][0]; + + for (int i=0; i<5; i++) { + if (i==scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { + cfg->carrier_config.ul_grid_size[i] = scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + cfg->carrier_config.ul_k0[i] = scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->offsetToCarrier; + } + else { + cfg->carrier_config.ul_grid_size[i] = 0; + cfg->carrier_config.ul_k0[i] = 0; + } + } + + mac->nr_band = *scc->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR; + mac->frame_type = get_frame_type(mac->nr_band, get_softmodem_params()->numerology); + // cell config + + cfg->cell_config.phy_cell_id = mac->physCellId; + cfg->cell_config.frame_duplex_type = mac->frame_type; + + // SSB config + cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; + cfg->ssb_config.scs_common = get_softmodem_params()->numerology; + + // SSB Table config + cfg->ssb_table.ssb_offset_point_a = scc->downlinkConfigCommon.frequencyInfoDL.offsetToPointA; + cfg->ssb_table.ssb_period = scc->ssb_PeriodicityServingCell; + cfg->ssb_table.ssb_subcarrier_offset = mac->ssb_subcarrier_offset; + + if (mac->frequency_range == FR1){ + cfg->ssb_table.ssb_mask_list[0].ssb_mask = scc->ssb_PositionsInBurst.inOneGroup.buf[0]<<24; + cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; + } + else{ + for (int i=0; i<8; i++){ + if ((scc->ssb_PositionsInBurst.groupPresence->buf[0]>>(7-i))&0x01) + cfg->ssb_table.ssb_mask_list[i>>2].ssb_mask |= scc->ssb_PositionsInBurst.inOneGroup.buf[0]<<(24-8*(i%4)); + } + } + + // TDD Table Configuration + if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 == NULL) + cfg->tdd_table.tdd_period = scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity; + else { + AssertFatal(scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL, + "scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n"); + cfg->tdd_table.tdd_period = *scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; + } + if(cfg->cell_config.frame_duplex_type == TDD){ + LOG_I(MAC,"Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period); + int return_tdd = set_tdd_config_nr_ue(cfg, + scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols + ); + + if (return_tdd !=0) + LOG_E(PHY,"TDD configuration can not be done\n"); + else + LOG_I(PHY,"TDD has been properly configurated\n"); + } + + // PRACH configuration + + uint8_t nb_preambles = 64; + if(scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) + nb_preambles = *scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; + + cfg->prach_config.prach_sequence_length = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present-1; + + if (scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) + cfg->prach_config.prach_sub_c_spacing = *scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; + else + cfg->prach_config.prach_sub_c_spacing = scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + cfg->prach_config.restricted_set_config = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->restrictedSetConfig; + + switch (scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM) { + case 0 : + cfg->prach_config.num_prach_fd_occasions = 1; + break; + case 1 : + cfg->prach_config.num_prach_fd_occasions = 2; + break; + case 2 : + cfg->prach_config.num_prach_fd_occasions = 4; + break; + case 3 : + cfg->prach_config.num_prach_fd_occasions = 8; + break; + default: + AssertFatal(1==0,"msg1 FDM identifier %ld undefined (0,1,2,3) \n", scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM); + } + + cfg->prach_config.num_prach_fd_occasions_list = (fapi_nr_num_prach_fd_occasions_t *) malloc(cfg->prach_config.num_prach_fd_occasions*sizeof(fapi_nr_num_prach_fd_occasions_t)); + for (int i=0; iprach_config.num_prach_fd_occasions; i++) { + cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i; + if (cfg->prach_config.prach_sequence_length) + cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; + else + cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839; + cfg->prach_config.num_prach_fd_occasions_list[i].k1 = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + + scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart + + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing, scc->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing ) * i); + cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; + cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup, + nb_preambles, mac->frame_type, mac->frequency_range); + //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ??? + } + cfg->prach_config.ssb_per_rach = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present-1; + +} + void config_common_ue(NR_UE_MAC_INST_t *mac, - module_id_t module_id, - int cc_idP) { + module_id_t module_id, + int cc_idP) { fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; NR_ServingCellConfigCommon_t *scc = mac->scc; @@ -280,7 +440,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) cfg->prach_config.prach_sub_c_spacing = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; - else + else cfg->prach_config.prach_sub_c_spacing = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; cfg->prach_config.restricted_set_config = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig; @@ -306,7 +466,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, for (i=0; iprach_config.num_prach_fd_occasions; i++) { cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i; if (cfg->prach_config.prach_sequence_length) - cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; + cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; else cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839; @@ -444,15 +604,12 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ } -int nr_rrc_mac_config_req_ue( - module_id_t module_id, - int cc_idP, - uint8_t gNB_index, - NR_MIB_t *mibP, - // NR_ServingCellConfigCommon_t *sccP, - // NR_MAC_CellGroupConfig_t *mac_cell_group_configP, - // NR_PhysicalCellGroupConfig_t *phy_cell_group_configP, - NR_CellGroupConfig_t *cell_group_config ){ +int nr_rrc_mac_config_req_ue(module_id_t module_id, + int cc_idP, + uint8_t gNB_index, + NR_MIB_t *mibP, + NR_ServingCellConfigCommonSIB_t *sccP, + NR_CellGroupConfig_t *cell_group_config){ NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); RA_config_t *ra = &mac->ra; @@ -462,7 +619,19 @@ int nr_rrc_mac_config_req_ue( if(mibP != NULL){ mac->mib = mibP; // update by every reception } - + if (sccP != NULL) { + mac->scc_SIB=sccP; + LOG_D(MAC,"Keeping ServingCellConfigCommonSIB\n"); + config_common_ue_sa(mac,module_id,cc_idP); + int num_slots_ul = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if (mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols>0) num_slots_ul++; + LOG_I(MAC, "Initializing ul_config_request. num_slots_ul = %d\n", num_slots_ul); + mac->ul_config_request = (fapi_nr_ul_config_request_t *)calloc(num_slots_ul, sizeof(fapi_nr_ul_config_request_t)); + // Setup the SSB to Rach Occasions mapping according to the config + build_ssb_to_ro_map(mac);//->scc, mac->phy_config.config_req.cell_config.frame_duplex_type); + mac->if_module->phy_config_request(&mac->phy_config); + mac->common_configuration_complete = 1; + } if(cell_group_config != NULL ){ mac->scg = cell_group_config; mac->servCellIndex = *cell_group_config->spCellConfig->servCellIndex; @@ -476,7 +645,7 @@ int nr_rrc_mac_config_req_ue( } // Setup the SSB to Rach Occasions mapping according to the config - build_ssb_to_ro_map(mac->scc, mac->phy_config.config_req.cell_config.frame_duplex_type); + build_ssb_to_ro_map(mac); /* if(mac_cell_group_configP != NULL){ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 7535193ff8..ebcdb79e0e 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -314,6 +314,7 @@ typedef struct { NR_CSI_ReportConfig_t *csirc; long physCellId; //// MAC config + int common_configuration_complete; NR_DRX_Config_t *drx_Config; NR_SchedulingRequestConfig_t *schedulingRequestConfig; NR_BSR_Config_t *bsr_Config; @@ -381,6 +382,7 @@ typedef struct { NR_ControlResourceSet_t *coreset0; frequency_range_t frequency_range; uint16_t nr_band; + uint8_t ssb_subcarrier_offset; } NR_UE_MAC_INST_t; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index a425ba29d2..b26ab7c783 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -83,7 +83,7 @@ int nr_rrc_mac_config_req_ue( int cc_idP, uint8_t gNB_index, NR_MIB_t *mibP, - //NR_ServingCellConfigCommon_t *sccP, + NR_ServingCellConfigCommonSIB_t *sccP, NR_CellGroupConfig_t *cell_group_config); /**\brief initialization NR UE MAC instance(s), total number of MAC instance based on NB_NR_UE_MAC_INST*/ @@ -313,7 +313,7 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu, uint8_t *nb_dmrs_re_per_rb, uint16_t *number_dmrs_symbols); -void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired); +void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac); void config_bwp_ue(NR_UE_MAC_INST_t *mac, uint16_t *bwp_ind, uint8_t *dci_format); diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index c991e74739..7f4de750ac 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -51,7 +51,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { //init mac here nr_ue_mac_inst = (NR_UE_MAC_INST_t *)calloc(sizeof(NR_UE_MAC_INST_t),NB_NR_UE_MAC_INST); if (rrc_inst) { - nr_rrc_mac_config_req_ue(0,0,0,NULL,rrc_inst->cell_group_config); + nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,rrc_inst->cell_group_config); if (IS_SOFTMODEM_NOS1){ AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); pdcp_layer_init(); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 3ce8403f67..c4922f1163 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -143,6 +143,7 @@ int8_t nr_ue_decode_mib(module_id_t module_id, //storing ssb index in the mac structure mac->mib_ssb = ssb_index; + mac->ssb_subcarrier_offset = ssb_subcarrier_offset; uint8_t scs_ssb; uint32_t band; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 8931e3b4fa..03b18773fc 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -982,7 +982,7 @@ int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, } // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config -static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { +static void build_ro_list(NR_UE_MAC_INST_t *mac) { int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers @@ -1000,7 +1000,6 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { int nb_fdm; uint8_t config_index, mu; - uint32_t pointa; int msg1_FDM; uint8_t prach_conf_period_idx; @@ -1008,18 +1007,21 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { uint8_t prach_conf_period_frame_idx; int64_t *prach_config_info_p; - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; + NR_RACH_ConfigCommon_t *setup = (mac->scc) ? + mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup: + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; config_index = rach_ConfigGeneric->prach_ConfigurationIndex; if (setup->msg1_SubcarrierSpacing) + //L139 mu = *setup->msg1_SubcarrierSpacing; else - mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + //L839 I don't think this is supported by UE looking at the code below + AssertFatal(1==0,"Long PRACH not supported\n"); - pointa = frequencyInfoDL->absoluteFrequencyPointA; msg1_FDM = rach_ConfigGeneric->msg1_FDM; switch (msg1_FDM){ @@ -1037,12 +1039,14 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { // ============================== // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule + int unpaired = mac->phy_config.config_req.cell_config.frame_duplex_type; + + prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, unpaired); + // Identify the proper PRACH Configuration Index table according to the operating frequency - LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired); + LOG_D(MAC,"mu = %u, PRACH config index = %u, unpaired = %u\n", mu, config_index, unpaired); - prach_config_info_p = get_prach_config_info(pointa, config_index, unpaired); - - if (pointa > 2016666) { //FR2 + if (mac->frequency_range == FR2) { //FR2 x = prach_config_info_p[2]; y = prach_config_info_p[3]; @@ -1160,7 +1164,7 @@ static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { } // Build the list of all the valid/transmitted SSBs according to the config -static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { +static void build_ssb_list(NR_UE_MAC_INST_t *mac) { // Create the list of transmitted SSBs // =================================== @@ -1168,68 +1172,91 @@ static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { uint64_t ssb_positionsInBurst; uint8_t ssb_idx = 0; - switch (scc->ssb_PositionsInBurst->present) { - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; + if (mac->scc) { + NR_ServingCellConfigCommon_t *scc = mac->scc; + switch (scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; } - ssb_idx++; - } - break; - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; } - ssb_idx++; - } - break; - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; - ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; } - ssb_idx++; + break; + default: + AssertFatal(false,"ssb_PositionsInBurst not present\n"); + break; + } + } else { // This is configuration from SIB1 + + AssertFatal(mac->scc_SIB->ssb_PositionsInBurst.groupPresence == NULL, "Handle case for >8 SSBs\n"); + ssb_bitmap = &mac->scc_SIB->ssb_PositionsInBurst.inOneGroup; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); } - break; - default: - AssertFatal(false,"ssb_PositionsInBurst not present\n"); - break; + ssb_idx++; + } } } // Map the transmitted SSBs to the ROs and create the association pattern according to the config -static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { +static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac) { // Map SSBs to PRACH occasions // =========================== // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_RACH_ConfigCommon_t *setup = (mac->scc) ? + mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup: + mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB @@ -1290,8 +1317,11 @@ static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { else { required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio; } - - required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion; + AssertFatal(prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion>0, + "prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion shouldn't be 0 (ssb_list.nb_tx_ssb %d, ssb_rach_ratio %d\n", + ssb_list.nb_tx_ssb,ssb_rach_ratio); + required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion; if (required_nb_of_prach_conf_period == 1) { prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1; @@ -1578,7 +1608,7 @@ static int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, } // Build the SSB to RO mapping upon RRC configuration update -void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){ +void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac) { // Clear all the lists and maps memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); @@ -1586,15 +1616,15 @@ void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){ // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config LOG_D(MAC,"Build RO list\n"); - build_ro_list(scc, unpaired); + build_ro_list(mac); // Build the list of all the valid/transmitted SSBs according to the config LOG_D(MAC,"Build SSB list\n"); - build_ssb_list(scc); + build_ssb_list(mac); // Map the transmitted SSBs to the ROs and create the association pattern according to the config LOG_D(MAC,"Map SSB to RO\n"); - map_ssb_to_ro(scc); + map_ssb_to_ro(mac); LOG_D(MAC,"Map SSB to RO done\n"); } diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 6c28beec34..10d7a2f9c6 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -418,7 +418,14 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, nrMultiBandInfo->freqBandIndicatorNR = configuration->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[i]; ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list,nrMultiBandInfo); } - sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA = configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; + int ref_scs; + if (configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) + ref_scs = 0; // 15 khz + if (configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) + ref_scs = 3; // 60 khz + uint32_t absolute_diff = (*configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); + sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA = + (absolute_diff/12) - (10<<(configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing - ref_scs)); for(int i = 0; i< configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.count; i++) { ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list,configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[i]); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 312293abdc..afbd05530b 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -589,7 +589,7 @@ int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message( // (void *)&bcch_message->message.choice.mib, // sizeof(NR_MIB_t) ); - nr_rrc_mac_config_req_ue( 0, 0, 0, mib, NULL); + nr_rrc_mac_config_req_ue( 0, 0, 0, mib, NULL, NULL); } return 0; @@ -1198,12 +1198,16 @@ int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message( // FIXME: improve condition for the RA trigger // Check for on-demand not broadcasted SI check_requested_SI_List(module_id, NR_UE_rrc_inst[module_id].requested_SI_List, *sib1); - if( nr_rrc_get_state(module_id) == RRC_STATE_IDLE_NR ) { + if( nr_rrc_get_state(module_id) <= RRC_STATE_IDLE_NR ) { NR_UE_rrc_inst[module_id].ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE; - // TODO: remove flag after full RA procedures implemented - get_softmodem_params()->do_ra = 1; + LOG_I(PHY,"Setting state to NR_RRC_SI_RECEIVED\n"); + nr_rrc_set_state (module_id, NR_RRC_SI_RECEIVED); } - nr_rrc_ue_generate_ra_msg(module_id,gNB_index); + // take ServingCellConfigCommon and configure L1/L2 + NR_UE_rrc_inst[module_id].servingCellConfigCommonSIB = sib1->servingCellConfigCommon; + nr_rrc_mac_config_req_ue(module_id,0,0,NULL,sib1->servingCellConfigCommon,NULL); + nr_rrc_ue_generate_ra_msg(module_id,gNB_index); + } else { LOG_E(NR_RRC, "SIB1 not decoded\n"); } diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index f4ce474657..94e3cfc1a4 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -105,6 +105,7 @@ typedef struct NR_UE_RRC_INST_s { NR_MeasConfig_t *meas_config; NR_CellGroupConfig_t *cell_group_config; + NR_ServingCellConfigCommonSIB_t *servingCellConfigCommonSIB; NR_RadioBearerConfig_t *radio_bearer_config; NR_MeasObjectToAddMod_t *MeasObj[NB_CNX_UE][MAX_MEAS_OBJ]; From 9fe3289cc05f25f27ac9103c44918e8d0303365d Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 14 Apr 2021 15:55:01 +0200 Subject: [PATCH 049/185] fix in nr-ue for ul slots --- executables/nr-ue.c | 12 ++++++++++-- openair2/LAYER2/NR_MAC_UE/config_ue.c | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 2bb6f4d686..f21bf7aacd 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -674,8 +674,16 @@ void *UE_thread(void *arg) { if (openair0_cfg[0].duplex_mode == duplex_mode_TDD) { uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots; - int nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSlots != 0); + int nrofUplinkSlots, nrofUplinkSymbols; + if (mac->scc) { + nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + nrofUplinkSymbols = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; + } + else { + nrofUplinkSlots = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + nrofUplinkSymbols = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; + } + uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSymbols != 0); uint8_t first_tx_slot = tdd_period - num_UL_slots; if (slot_tx_usrp % tdd_period == first_tx_slot) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 9797db6168..85fb745012 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -260,7 +260,7 @@ void config_common_ue_sa(NR_UE_MAC_INST_t *mac, if (scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) cfg->prach_config.prach_sub_c_spacing = *scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; - else + else cfg->prach_config.prach_sub_c_spacing = scc->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; cfg->prach_config.restricted_set_config = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->restrictedSetConfig; @@ -286,7 +286,7 @@ void config_common_ue_sa(NR_UE_MAC_INST_t *mac, for (int i=0; iprach_config.num_prach_fd_occasions; i++) { cfg->prach_config.num_prach_fd_occasions_list[i].num_prach_fd_occasions = i; if (cfg->prach_config.prach_sequence_length) - cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; + cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139; else cfg->prach_config.num_prach_fd_occasions_list[i].prach_root_sequence_index = scc->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l839; cfg->prach_config.num_prach_fd_occasions_list[i].k1 = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + From a170257d62ec4a86c4b417dd4af829ccdaa87a65 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 15 Apr 2021 15:33:08 +0200 Subject: [PATCH 050/185] fix for RA SS --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 ++ openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 27 +++++++++++++++++-- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 3 +-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 16 ++--------- openair2/RRC/NR_UE/L2_interface_ue.c | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 16 +++++------ 6 files changed, 38 insertions(+), 28 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index ccd7c8cb01..b1f2b05679 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -300,6 +300,8 @@ typedef struct { /// BeamfailurerecoveryConfig NR_BeamFailureRecoveryConfig_t RA_BeamFailureRecoveryConfig; + /// RA SearchSpace + NR_SearchSpace_t *ss; } RA_config_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 47c2bf128a..c6141355c3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -79,6 +79,29 @@ void init_RA(module_id_t mod_id, prach_resources->POWER_OFFSET_2STEP_RA = 0; prach_resources->RA_SCALING_FACTOR_BI = 1; + struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList; + NR_SearchSpaceId_t ss_id = 0; + NR_SearchSpace_t *ss = NULL; + if(mac->scc) { + commonSearchSpaceList = mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ss_id = *mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } + else { + if(mac->scc_SIB) { + commonSearchSpaceList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ss_id = *mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } + else + AssertFatal(1==0,"Both scc and scc_SIB are null\n"); + } + AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n"); + // Common searchspace list + for (int i = 0; i < commonSearchSpaceList->list.count; i++) { + ss = commonSearchSpaceList->list.array[i]; + if (ss->searchSpaceId == ss_id) + ra->ss = ss; + } + if (rach_ConfigDedicated) { if (rach_ConfigDedicated->cfra){ LOG_I(MAC, "Initialization of 2-step contention-free random access procedure\n"); @@ -682,8 +705,8 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac){ AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; long scs = (mac->scc) ? - &mac->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing : - &mac->scc_SIB->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + mac->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing : + mac->scc_SIB->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index e0ae8dfbf5..6bfbd9c417 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -861,12 +861,11 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in else { // this is for Msg2/Msg4 if (mac->ra.ra_state >= WAIT_RAR) { - NR_SearchSpace_t *ss0 = mac->search_space_zero; fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; rel15->num_dci_options = 1; rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; config_dci_pdu(mac, rel15, dl_config, mac->ra.ra_state == WAIT_RAR ? NR_RNTI_RA : NR_RNTI_TC , -1); - fill_dci_search_candidates(ss0, rel15); + fill_dci_search_candidates(mac->ra.ss, rel15); dl_config->number_pdus = 1; LOG_D(MAC,"mac->cg %p: Calling fill_scheduled_response rnti %x, type0_pdcch, num_pdus %d\n",mac->cg,rel15->rnti,dl_config->number_pdus); fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index f7c7cc5581..00045074f4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -897,13 +897,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra if(ra->ra_ss) { ss = ra->ra_ss; } else { - if (nr_mac->sched_ctrlCommon == NULL){ - nr_mac->sched_ctrlCommon = calloc(1,sizeof(*nr_mac->sched_ctrlCommon)); - } - if(nr_mac->sched_ctrlCommon->search_space == NULL) - AssertFatal(1==0,"This seach space should have been already filled in SIB1\n"); - else - ss = nr_mac->sched_ctrlCommon->search_space; + AssertFatal(1==0,"RA SS missing\n"); } NR_BWP_Downlink_t *bwp = NULL; @@ -1169,13 +1163,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra if(ra->ra_ss) { ss = ra->ra_ss; } else { - if (nr_mac->sched_ctrlCommon == NULL){ - nr_mac->sched_ctrlCommon = calloc(1,sizeof(*nr_mac->sched_ctrlCommon)); - } - if(nr_mac->sched_ctrlCommon->search_space == NULL) - AssertFatal(1==0,"This seach space should have been already filled in SIB1\n"); - else - ss = nr_mac->sched_ctrlCommon->search_space; + AssertFatal(1==0,"RA SS missing\n"); } NR_BWP_Downlink_t *bwp = ra->CellGroup ? ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1] : NULL; diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 1be3fb6225..be952d10d1 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -167,7 +167,7 @@ rrc_data_req_ue( TASK_RRC_UE, TASK_PDCP_UE, sdu_sizeP); - LOG_I(RRC,"Sending RRC message for SRB %ld, sdu_size %d\n",rb_idP,sdu_sizeP); + LOG_I(RRC,"Sending RRC message for SRB %ld, sdu_size %d\n",rb_idP,sdu_sizeP); memcpy (message_buffer, buffer_pP, sdu_sizeP); message_p = itti_alloc_new_message ( TASK_RRC_UE, 0, RRC_DCCH_DATA_REQ); RRC_DCCH_DATA_REQ (message_p).frame = ctxt_pP->frame; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index f7f5064553..968234cc96 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -553,7 +553,7 @@ int8_t nr_rrc_ue_decode_NR_BCCH_BCH_Message( uint8_t *const bufferP, const uint8_t buffer_len ){ - NR_BCCH_BCH_Message_t *bcch_message = NULL; + NR_BCCH_BCH_Message_t *bcch_message = NULL; if (NR_UE_rrc_inst[module_id].mib != NULL) SEQUENCE_free( &asn_DEF_NR_BCCH_BCH_Message, (void *)bcch_message, 1 ); @@ -1005,7 +1005,6 @@ int nr_decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index } if (new_sib == 1) { NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt++; - if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count) nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE ); @@ -1126,13 +1125,12 @@ int8_t nr_rrc_ue_generate_ra_msg(module_id_t module_id, uint8_t gNB_index) { return 0; } -int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message( - module_id_t module_id, - const uint8_t gNB_index, - uint8_t *const Sdu, - const uint8_t Sdu_len, - const uint8_t rsrq, - const uint8_t rsrp) { +int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id_t module_id, + const uint8_t gNB_index, + uint8_t *const Sdu, + const uint8_t Sdu_len, + const uint8_t rsrq, + const uint8_t rsrp) { NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; From 6b82ac26fc26bd88e1dd7a211347ffef44776e9b Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 16 Apr 2021 08:52:31 +0200 Subject: [PATCH 051/185] using common configuration complete to signal sib1 decoded --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 3 --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 3 ++- openair2/RRC/NR_UE/rrc_UE.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b1f2b05679..088e9a12f6 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -365,9 +365,6 @@ typedef struct { /// SSB index from MIB decoding uint8_t mib_ssb; - /// Flag for SIB1 - uint8_t sib1_received; - /// Last NDI of UL HARQ processes uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES]; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 4a5a74a2be..aba40c8cd8 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -152,7 +152,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, uint32_t band; uint16_t ssb_start_symbol; - if ((get_softmodem_params()->sa == 1) && (mac->sib1_received == 0)) { + if ((get_softmodem_params()->sa == 1) && (mac->common_configuration_complete == 0)) { + scs_ssb = get_softmodem_params()->numerology; band = mac->nr_band; ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 968234cc96..334faff9ea 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1189,7 +1189,7 @@ int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id_t module_id, check_requested_SI_List(module_id, NR_UE_rrc_inst[module_id].requested_SI_List, *sib1); if( nr_rrc_get_state(module_id) <= RRC_STATE_IDLE_NR ) { NR_UE_rrc_inst[module_id].ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE; - LOG_I(PHY,"Setting state to NR_RRC_SI_RECEIVED\n"); + LOG_I(NR_RRC,"Setting state to NR_RRC_SI_RECEIVED\n"); nr_rrc_set_state (module_id, NR_RRC_SI_RECEIVED); } // take ServingCellConfigCommon and configure L1/L2 From b968a88413c65123ba755229ee84e97be179e82a Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 16 Apr 2021 09:02:43 +0200 Subject: [PATCH 052/185] bugfix in ue sib1 scheduling --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index aba40c8cd8..c3d49d5398 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -152,21 +152,21 @@ int8_t nr_ue_decode_mib(module_id_t module_id, uint32_t band; uint16_t ssb_start_symbol; - if ((get_softmodem_params()->sa == 1) && (mac->common_configuration_complete == 0)) { + if (get_softmodem_params()->sa == 1) { scs_ssb = get_softmodem_params()->numerology; band = mac->nr_band; ssb_start_symbol = get_ssb_start_symbol(band,scs_ssb,ssb_index); - nr_ue_sib1_scheduler(module_id, - cc_id, - ssb_start_symbol, - frame, - ssb_subcarrier_offset, - ssb_index, - ssb_start_subcarrier, - mac->frequency_range); - + if (mac->common_configuration_complete == 0) + nr_ue_sib1_scheduler(module_id, + cc_id, + ssb_start_symbol, + frame, + ssb_subcarrier_offset, + ssb_index, + ssb_start_subcarrier, + mac->frequency_range); } else { NR_ServingCellConfigCommon_t *scc = mac->scc; From e6ad0aac74e0cb704483ef25c5085555f0111c9b Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 16 Apr 2021 17:34:05 +0200 Subject: [PATCH 053/185] fix for csi meas report --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 17e972284f..8ea7165a65 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -514,6 +514,7 @@ void nr_csi_meas_reporting(int Mod_idP, && curr_pucch->dai_c == 0, "PUCCH not free at index 2 for UE %04x\n", UE_info->rnti[UE_id]); + curr_pucch->r_pucch = -1; curr_pucch->frame = frame; curr_pucch->ul_slot = sched_slot; curr_pucch->resource_indicator = res_index; From a96501177e2af162465d1e35f6ada35c60210d3a Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sat, 17 Apr 2021 21:47:01 +0200 Subject: [PATCH 054/185] Code cleanup as per reiview comments --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 2 +- .../nr_dl_channel_estimation.c | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 539130a45c..d027b9ef91 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -605,7 +605,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch += 24; } } -#ifdef DEBUG_PDSCH +#ifdef DEBUG_PUSCH ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; for(uint16_t idxP=0; idxPframe_parms.nb_antennas_rx; aarx++) { - pil = (int16_t *)&pilot[rb_offset*((config_type==pdsch_dmrs_type1) ? 6:4)]; + pil = (int16_t *)&pilot[rb_offset*((config_type == pdsch_dmrs_type1) ? 6:4)]; k = k % ue->frame_parms.ofdm_symbol_size; re_offset = k; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+re_offset+nushift)]; dl_ch = (int16_t *)&dl_ch_estimates[p*ue->frame_parms.nb_antennas_rx+aarx][ch_offset]; memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size)); - if (ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha + if (ue->high_speed_flag == 0) // multiply previous channel estimate by ch_est_alpha multadd_complex_vector_real_scalar(dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), ue->ch_est_alpha,dl_ch-(ue->frame_parms.ofdm_symbol_size<<1), 1,ue->frame_parms.ofdm_symbol_size); @@ -848,18 +848,12 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, dl_ch, 8); - //for (int i= 0; i<16; i++) - //printf("dl_ch addr %p %d\n", dl_ch+i, *(dl_ch+i)); - pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; dl_ch += 8; for (pilot_cnt=3; pilot_cnt<(6*nb_rb_pdsch-3); pilot_cnt += 2) { - //if ((pilot_cnt%6)==0) - //dl_ch += 4; - //printf("re_offset %d\n",re_offset); ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -941,7 +935,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, uint16_t idxDC = 2*(ue->frame_parms.ofdm_symbol_size - bwp_start_subcarrier); uint16_t idxPil = idxDC/2; re_offset = k; - pil = (int16_t *)&pilot[rb_offset*((config_type==pdsch_dmrs_type1) ? 6:4)]; + pil = (int16_t *)&pilot[rb_offset*((config_type == pdsch_dmrs_type1) ? 6:4)]; pil += (idxPil-2); dl_ch += (idxDC-4); dl_ch = memset(dl_ch, 0, sizeof(int16_t)*10); @@ -951,7 +945,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); // for proper allignment of SIMD vectors - if((ue->frame_parms.N_RB_DL&1)==0) { + if((ue->frame_parms.N_RB_DL&1) == 0) { multadd_real_vector_complex_scalar(fdcl, ch, @@ -987,7 +981,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, 8); } } - } else if (config_type==pdsch_dmrs_type2 && ue->fd_lin_interpolation == 1){ //pdsch_dmrs_type2 |dmrs_r,dmrs_l,0,0,0,0,dmrs_r,dmrs_l,0,0,0,0| + } else if (config_type == pdsch_dmrs_type2 && ue->fd_lin_interpolation == 1){ //pdsch_dmrs_type2 |dmrs_r,dmrs_l,0,0,0,0,dmrs_r,dmrs_l,0,0,0,0| // Treat first 4 pilots specially (left edge) ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -1150,7 +1144,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch_l[1]= dl_ch[1] ; // for proper allignment of SIMD vectors - if((ue->frame_parms.N_RB_DL&1)==0) { + if((ue->frame_parms.N_RB_DL&1) == 0) { dl_ch -= 20; //Interpolate fdcrl1 with ch_r multadd_real_vector_complex_scalar(filt8_dcrl1, From c8ba34cf87b61efdef3d5f588de4df78ef8672f9 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 20 Apr 2021 11:58:55 +0200 Subject: [PATCH 055/185] fix in extract dci --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 05a7edbac2..8fbb94d45c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1186,7 +1186,7 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, switch(rnti_type) { case NR_RNTI_RA: // check BWP id - if (mac->cg) N_RB=NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + if (mac->DLbwp[0]) N_RB=NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); else N_RB=NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); // Freq domain assignment @@ -1225,10 +1225,6 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, case NR_RNTI_C: - // check BWP id - if (mac->cg) N_RB=NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - else N_RB=NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - //Identifier for DCI formats pos++; dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; @@ -1423,8 +1419,8 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, case NR_RNTI_TC: // check BWP id - if (mac->cg) N_RB=NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - else N_RB=NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + if (mac->DLbwp[0]) N_RB=NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + else N_RB=NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); // indicating a DL DCI format 1bit pos++; From f31badef03b615c0c1445750a61b0cf67ec17518 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 20 Apr 2021 15:54:38 +0200 Subject: [PATCH 056/185] ssb_start_subcarrier from command line --- executables/nr-uesoftmodem.c | 2 +- executables/nr-uesoftmodem.h | 1 + openair1/PHY/INIT/nr_parms.c | 8 -------- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 2 +- targets/RT/USER/lte-softmodem.h | 1 + 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 4aaaf3e058..6df9e32e5f 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -276,7 +276,7 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->mode = normal_txrx; - config_process_cmdline( cmdline_params,numparams,NULL); + config_get(cmdline_params,numparams,NULL); int pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRX_OPT); if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue; diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index ce994b4a1f..faa1e3eca6 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -58,6 +58,7 @@ {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ {"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:106, TYPE_UINT, 0}, \ + {"s" , CONFIG_HLP_SSC, 0, u16ptr:&(fp->ssb_start_subcarrier), defintval:516, TYPE_UINT16,0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ } diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 5e4895ca1c..2f3d9455d2 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -369,14 +369,6 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink frame_parms->get_samples_slot_timestamp = &get_samples_slot_timestamp; frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe; - // setting initial ssb start subcarrier to have SSBs at BW center - frame_parms->ssb_start_subcarrier = ((frame_parms->N_RB_DL>>1)-10)*12; - - if(frame_parms->nb_antennas_rx == 0) - frame_parms->nb_antennas_rx = 1; - if(frame_parms->nb_antennas_tx == 0) - frame_parms->nb_antennas_tx = 1; - } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index c6141355c3..9c52942763 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -686,7 +686,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, nr_ue_contention_resolution(mod_id, CC_id, frame, nr_slot_tx, prach_resources); } - LOG_I(MAC,"ra->generate_nr_prach %d ra->ra_state %d (GENERATE_IDLE %d)\n",ra->generate_nr_prach,ra->ra_state,GENERATE_IDLE); + LOG_D(MAC,"ra->generate_nr_prach %d ra->ra_state %d (GENERATE_IDLE %d)\n",ra->generate_nr_prach,ra->ra_state,GENERATE_IDLE); if(ra->generate_nr_prach != GENERATE_IDLE) { return ra->generate_nr_prach; } else { diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index 1c537dabe3..4adab5fa24 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -78,6 +78,7 @@ #define CONFIG_HLP_UESCAN "set UE to scan around carrier\n" #define CONFIG_HLP_EMULIFACE "Set the interface name for the multicast transport for emulation mode (e.g. eth0, lo, etc.) \n" #define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n" +#define CONFIG_HLP_SSC "Set the start subcarrier \n" #define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n" #define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n" #define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n" From d2752d0dc5ccb232067a1c9d84a6d84663574f57 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 21 Apr 2021 13:20:24 +0200 Subject: [PATCH 057/185] NR_UE: fix allocation of txdataF_layers Each element is sizeof(int32_t), not sizeof(int32_t *). --- openair1/PHY/INIT/nr_init_ue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 855acc01ff..c68f5d38db 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -123,7 +123,7 @@ void phy_init_nr_ue_PUSCH(NR_UE_PUSCH *const pusch, AssertFatal( pusch, "pusch==0" ); for (int i=0; itxdataF_layers[i] = (int32_t *)malloc16_clear((NR_MAX_PUSCH_ENCODED_LENGTH)*sizeof(int32_t *)); + pusch->txdataF_layers[i] = (int32_t *)malloc16_clear(NR_MAX_PUSCH_ENCODED_LENGTH*sizeof(int32_t)); } } From 5d6c01de915fdac7bc0454bdb1847e9175f2786e Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 21 Apr 2021 13:23:27 +0200 Subject: [PATCH 058/185] nr_ulsim: fix for nb_antennas_tx != nb_antennas_rx use nb_antennas_tx instead of nb_antennas_rx when copying data from UE->common_vars.txdata to s_re and s_im --- openair1/SIMULATION/NR_PHY/ulsim.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index d8537c4207..bd2e76ee6f 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -767,7 +767,11 @@ int main(int argc, char **argv) nr_scheduled_response_t scheduled_response; fapi_nr_ul_config_request_t ul_config; fapi_nr_tx_request_t tx_req; - + + memset(&scheduled_response, 0, sizeof(scheduled_response)); + memset(&ul_config, 0, sizeof(ul_config)); + memset(&tx_req, 0, sizeof(tx_req)); + uint8_t ptrs_mcs1 = 2; uint8_t ptrs_mcs2 = 4; uint8_t ptrs_mcs3 = 10; @@ -1130,7 +1134,7 @@ int main(int argc, char **argv) frame_parms->ofdm_symbol_size/(12*nb_rb)); for (i=0; inb_antennas_rx; aa++) { + for (int aa=0; aanb_antennas_tx; aa++) { s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)]); s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]); } From fd70cd3e445583b37a7b22a8a6329001b80b8a72 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 21 Apr 2021 13:26:48 +0200 Subject: [PATCH 059/185] gNB: fix possible overflow in PRB based PUSCH channel estimation --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 374feac75b..fe945bfba6 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -520,49 +520,52 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB for (pilot_cnt=0; pilot_cnt<6*nb_rb_pusch; pilot_cnt += 6) { - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0]/=6; - ch[1]/=6; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; @@ -571,36 +574,38 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB for (pilot_cnt=0; pilot_cnt<4*nb_rb_pusch; pilot_cnt += 4) { - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] /=4 ; - ch[1] /=4 ; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; From b110c3622b35c752a94a7de1d5bb066e80e5db78 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 21 Apr 2021 13:37:35 +0200 Subject: [PATCH 060/185] NR_UE: fix possible overflow in PRB based PDSCH channel estimation --- .../nr_dl_channel_estimation.c | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) 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 7fedecc426..ab9a42c60d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1200,49 +1200,52 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, else if (config_type == pdsch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB for (pilot_cnt=0; pilot_cnt<6*nb_rb_pdsch; pilot_cnt += 6) { - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0]/=6; - ch[1]/=6; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; @@ -1251,36 +1254,38 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB for (pilot_cnt=0; pilot_cnt<4*nb_rb_pdsch; pilot_cnt += 4) { - ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] += (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); - ch[1] += (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); - + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; - ch[0] /=4 ; - ch[1] /=4 ; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; From 87b53883b27a472f26e9135f557bd37d3f5c001c Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 21 Apr 2021 13:38:57 +0200 Subject: [PATCH 061/185] HACK: cut PUSCH and PDSCH OFDM symbol after complete CP Currently we cute the PUSCH and PDSCH OFDM symbols starting within the last 1/8th of the CP to avoid ISI. This time shift leads to a rotation in frequency domain. The current PRB based channel estimation does not compensate for the rotation _within_ a PRB, leading to bad performance. This commit should _not_ make it into develop branch, it is just for testing! Instead, we should do some compensating rotation before channel estimation. --- openair1/PHY/MODULATION/slot_fep_nr.c | 4 ++-- openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c | 2 +- openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 0be635ba0b..bcd20e06f3 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -107,7 +107,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, rx_offset += frame_parms->ofdm_symbol_size * symbol; // use OFDM symbol from within 1/8th of the CP to avoid ISI - rx_offset -= nb_prefix_samples / 8; + //rx_offset -= nb_prefix_samples / 8; #ifdef DEBUG_FEP // if (ue->frame <100) @@ -296,7 +296,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, // offset of n-th OFDM symbol rxdata_offset += symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples); // use OFDM symbol from within 1/8th of the CP to avoid ISI - rxdata_offset -= nb_prefix_samples / 8; + //rxdata_offset -= nb_prefix_samples / 8; int16_t *rxdata_ptr; diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index d3e33a91a8..5ac5a5fa35 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -45,7 +45,7 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; - int sync_pos = frame_parms->nb_prefix_samples / 8; + int sync_pos = 0; // frame_parms->nb_prefix_samples / 8; for (i = 0; i < frame_parms->ofdm_symbol_size; i++) { int temp = 0; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index 0318ed6478..475d418083 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -82,7 +82,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, // do not filter to have proactive timing adjustment //max_pos_fil = max_pos; - diff = max_pos_fil - (frame_parms->nb_prefix_samples>>3); + diff = max_pos_fil; // - (frame_parms->nb_prefix_samples>>3); if (frame_parms->freq_range==nr_FR2) sync_offset = 2; From 945a020f93aec9cb25343d746284110c7c0064d8 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 23 Apr 2021 13:46:29 +0200 Subject: [PATCH 062/185] Added linear phase derotation in UL This is necessary to compensate the rotation caused by the timeshifted OFDM symbol (1/8 CP) --- openair1/PHY/INIT/nr_init.c | 1 + openair1/PHY/MODULATION/nr_modulation.c | 69 +++++++++++++++++++++++++ openair1/PHY/MODULATION/slot_fep_nr.c | 15 +++++- openair1/PHY/defs_nr_common.h | 3 ++ 4 files changed, 87 insertions(+), 1 deletion(-) 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 From 1991c2f9cdee374e23a6845b534a651c21d6a90d Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 23 Apr 2021 15:42:16 +0200 Subject: [PATCH 063/185] Revert "HACK: cut PUSCH and PDSCH OFDM symbol after complete CP" This reverts commit 87b53883b27a472f26e9135f557bd37d3f5c001c. --- openair1/PHY/MODULATION/slot_fep_nr.c | 4 ++-- openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c | 2 +- openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 9c77fd765d..5a6a5ed625 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -107,7 +107,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, rx_offset += frame_parms->ofdm_symbol_size * symbol; // use OFDM symbol from within 1/8th of the CP to avoid ISI - //rx_offset -= nb_prefix_samples / 8; + rx_offset -= nb_prefix_samples / 8; #ifdef DEBUG_FEP // if (ue->frame <100) @@ -296,7 +296,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, // offset of n-th OFDM symbol rxdata_offset += symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples); // use OFDM symbol from within 1/8th of the CP to avoid ISI - //rxdata_offset -= nb_prefix_samples / 8; + rxdata_offset -= nb_prefix_samples / 8; int16_t *rxdata_ptr; diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 5ac5a5fa35..d3e33a91a8 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -45,7 +45,7 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; - int sync_pos = 0; // frame_parms->nb_prefix_samples / 8; + int sync_pos = frame_parms->nb_prefix_samples / 8; for (i = 0; i < frame_parms->ofdm_symbol_size; i++) { int temp = 0; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index 475d418083..0318ed6478 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -82,7 +82,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, // do not filter to have proactive timing adjustment //max_pos_fil = max_pos; - diff = max_pos_fil; // - (frame_parms->nb_prefix_samples>>3); + diff = max_pos_fil - (frame_parms->nb_prefix_samples>>3); if (frame_parms->freq_range==nr_FR2) sync_offset = 2; From 11111bcd6802ab464fc4f9dacdc8939fc923fab1 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 23 Apr 2021 16:22:28 +0200 Subject: [PATCH 064/185] Adding freq domain deroration to DL also fixed build wanings --- executables/nr-uesoftmodem.c | 1 + openair1/PHY/MODULATION/nr_modulation.c | 1 - openair1/PHY/MODULATION/nr_modulation.h | 2 ++ openair1/PHY/MODULATION/slot_fep_nr.c | 13 +++++++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index ef50e34008..3b27716ed6 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -470,6 +470,7 @@ int main( int argc, char **argv ) { nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); init_symbol_rotation(&UE[CC_id]->frame_parms); + init_timeshift_rotation(&UE[CC_id]->frame_parms); init_nr_ue_vars(UE[CC_id], 0, abstraction_flag); #ifdef FR2_TEST diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index efa18db2a3..954cabc21d 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -749,7 +749,6 @@ 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; diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 547d20952f..75541a1361 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -117,6 +117,8 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, void init_symbol_rotation(NR_DL_FRAME_PARMS *fp); +void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp); + void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, int slot, diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 5a6a5ed625..10c25ea7bc 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -157,6 +157,19 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], frame_parms->ofdm_symbol_size, 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 *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + shift_rot, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + 1, + frame_parms->ofdm_symbol_size, + 15); } #ifdef DEBUG_FEP From 215f263a69f4259049752fdf5fb9310fcc4b6ece Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sun, 25 Apr 2021 21:05:56 +0200 Subject: [PATCH 065/185] Making sample offset as cmd line parameter for gNB its in L1 section of config file for UE its a cmd line paramenter --- executables/nr-uesoftmodem.c | 3 +++ executables/nr-uesoftmodem.h | 5 +++- openair1/PHY/INIT/nr_init.c | 2 ++ openair1/PHY/MODULATION/nr_modulation.c | 24 +++++++++---------- openair1/PHY/MODULATION/slot_fep_nr.c | 16 ++++--------- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 2 +- .../PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c | 2 +- openair1/PHY/defs_gNB.h | 2 ++ openair1/PHY/defs_nr_common.h | 2 ++ openair1/SIMULATION/NR_PHY/dlsim.c | 1 + openair1/SIMULATION/NR_PHY/pbchsim.c | 3 +++ openair1/SIMULATION/NR_PHY/ulsim.c | 1 + openair2/GNB_APP/L1_nr_paramdef.h | 5 +++- openair2/GNB_APP/gnb_config.c | 1 + .../CONF/gnb.band78.tm1.106PRB.usrpn300.conf | 1 + 15 files changed, 42 insertions(+), 28 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 3b27716ed6..670748c275 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -242,6 +242,7 @@ void init_tpools(uint8_t nun_dlsch_threads) { } static void get_options(void) { + nrUE_params.ofdm_offset_divisor = 8; paramdef_t cmdline_params[] =CMDLINE_NRUEPARAMS_DESC ; int numparams = sizeof(cmdline_params)/sizeof(paramdef_t); config_process_cmdline( cmdline_params,numparams,NULL); @@ -325,6 +326,8 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs); + fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor; + } void init_openair0(void) { diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 3345aafd26..7f25a9f9fa 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -8,7 +8,8 @@ -#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization" +#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n" +#define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument when calling config_get or config_getlist functions */ @@ -29,6 +30,7 @@ {"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:(char **)&usrp_args, defstrval:"type=b200", TYPE_STRING, 0}, \ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ {"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, iptr:(int32_t *)&nrUE_params.nr_dlsch_parallel, defintval:0, TYPE_UINT8, 0}, \ + {"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, uptr:(uint32_t *)&nrUE_params.ofdm_offset_divisor, defuintval:UINT_MAX, TYPE_UINT32, 0}, \ {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ {"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, iptr:&vcdflag, defintval:0, TYPE_INT, 0}, \ {"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH,0, strptr:(char **)&rrc_config_path, defstrval:"./", TYPE_STRING, 0} \ @@ -66,6 +68,7 @@ typedef struct { uint64_t optmask; //mask to store boolean config options + uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol uint8_t nr_dlsch_parallel; // number of threads for dlsch decoding, 0 means no parallelization tpool_t Tpool; // thread pool } nrUE_params_t; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 34ea60f02c..ca49fe6ce1 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -483,6 +483,7 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band); nr_init_frame_parms(gNB_config, fp); + fp->ofdm_offset_divisor = UINT_MAX; gNB->configured = 1; LOG_I(PHY,"gNB configured\n"); } @@ -534,6 +535,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { // } RC.gNB[Mod_id]->configured = 1; + fp->ofdm_offset_divisor = RC.gNB[Mod_id]->ofdm_offset_divisor; init_symbol_rotation(fp); init_timeshift_rotation(fp); diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 954cabc21d..d38373afff 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -762,7 +762,7 @@ void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp) for (i = 0; i < fp->ofdm_symbol_size/2; i++) { timeshift_symbol_rotation = fp->timeshift_symbol_rotation[0]; f = fd * i; - t0 = Ncp0 / 8; + t0 = Ncp0 / fp->ofdm_offset_divisor; poff = 2 * M_PI * -t0 * Tc * f; exp_re = cos(poff); exp_im = sin(-poff); @@ -770,7 +770,7 @@ void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp) timeshift_symbol_rotation[i*2+1] = (int16_t)floor(exp_im * 32767); timeshift_symbol_rotation = fp->timeshift_symbol_rotation[1]; - t0 = Ncp1 / 8; + t0 = Ncp1 / fp->ofdm_offset_divisor; poff = 2 * M_PI * -t0 * Tc * f; exp_re = cos(poff); exp_im = sin(-poff); @@ -779,8 +779,8 @@ void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp) 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], + fp->timeshift_symbol_rotation[0][i*2], + fp->timeshift_symbol_rotation[0][i*2+1], poff); } @@ -789,25 +789,25 @@ void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp) 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; + t0 = Ncp0 / fp->ofdm_offset_divisor; 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[j*2] = (int16_t)ceil(exp_re * 32767); + timeshift_symbol_rotation[j*2+1] = (int16_t)ceil(exp_im * 32767); timeshift_symbol_rotation = fp->timeshift_symbol_rotation[1]; - t0 = Ncp1 / 8; + t0 = Ncp1 / fp->ofdm_offset_divisor; 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[j*2] = (int16_t)ceil(exp_re * 32767); + timeshift_symbol_rotation[j*2+1] = (int16_t)ceil(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], + fp->timeshift_symbol_rotation[0][j*2], + fp->timeshift_symbol_rotation[0][j*2+1], poff); i++; } diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 10c25ea7bc..2fe5901991 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -107,7 +107,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, rx_offset += frame_parms->ofdm_symbol_size * symbol; // use OFDM symbol from within 1/8th of the CP to avoid ISI - rx_offset -= nb_prefix_samples / 8; + rx_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor); #ifdef DEBUG_FEP // if (ue->frame <100) @@ -158,11 +158,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, frame_parms->ofdm_symbol_size, 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]; + int16_t *shift_rot = frame_parms->timeshift_symbol_rotation[0]; multadd_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], shift_rot, @@ -309,7 +305,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, // offset of n-th OFDM symbol rxdata_offset += symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples); // use OFDM symbol from within 1/8th of the CP to avoid ISI - rxdata_offset -= nb_prefix_samples / 8; + rxdata_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor); int16_t *rxdata_ptr; @@ -370,11 +366,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, 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]; + int16_t *shift_rot = frame_parms->timeshift_symbol_rotation[0]; multadd_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], shift_rot, diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index d3e33a91a8..36e1c3fee9 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -45,7 +45,7 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; - int sync_pos = frame_parms->nb_prefix_samples / 8; + int sync_pos = frame_parms->nb_prefix_samples / frame_parms->ofdm_offset_divisor; for (i = 0; i < frame_parms->ofdm_symbol_size; i++) { int temp = 0; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index 0318ed6478..f411e8d5b2 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -82,7 +82,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, // do not filter to have proactive timing adjustment //max_pos_fil = max_pos; - diff = max_pos_fil - (frame_parms->nb_prefix_samples>>3); + diff = max_pos_fil - (frame_parms->nb_prefix_samples / frame_parms->ofdm_offset_divisor); if (frame_parms->freq_range==nr_FR2) sync_offset = 2; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index ed43528088..b6119cad8c 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -776,6 +776,8 @@ typedef struct PHY_VARS_gNB_s { uint32_t max_peak_val; + /// OFDM symbol offset divisor for UL + uint32_t ofdm_offset_divisor; /// \brief sinr for all subcarriers of the current link (used only for abstraction). /// first index: ? [0..N_RB_DL*12[ double *sinr_dB; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index bd62bd3937..f89c3d66af 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -365,6 +365,8 @@ struct NR_DL_FRAME_PARMS { uint8_t ssb_index; /// PBCH polar encoder params t_nrPolar_params pbch_polar_params; + /// OFDM symbol offset divisor for UL + uint32_t ofdm_offset_divisor; }; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f099d9e622..da2937208e 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -619,6 +619,7 @@ int main(int argc, char **argv) memset(RC.gNB[0],0,sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; + gNB->ofdm_offset_divisor = UINT_MAX; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index c75a590603..2c9fb268f2 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -109,7 +109,9 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band); + fp->ofdm_offset_divisor = UINT_MAX; nr_init_frame_parms(gNB_config, fp); + init_timeshift_rotation(fp); init_symbol_rotation(fp); @@ -405,6 +407,7 @@ int main(int argc, char **argv) RC.gNB = (PHY_VARS_gNB**) malloc(sizeof(PHY_VARS_gNB *)); RC.gNB[0] = malloc(sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; + gNB->ofdm_offset_divisor = UINT_MAX; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) frame_parms->nb_antennas_tx = n_tx; frame_parms->nb_antennas_rx = n_rx; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index bd2e76ee6f..8f3d2a5cc9 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -616,6 +616,7 @@ int main(int argc, char **argv) RC.gNB = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *)); RC.gNB[0] = calloc(1,sizeof(PHY_VARS_gNB)); gNB = RC.gNB[0]; + gNB->ofdm_offset_divisor = UINT_MAX; gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); char tp_param[] = "n"; diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h index 88f2cb1615..2f58860161 100644 --- a/openair2/GNB_APP/L1_nr_paramdef.h +++ b/openair2/GNB_APP/L1_nr_paramdef.h @@ -47,6 +47,7 @@ #define CONFIG_STRING_L1_REMOTE_N_PORTD "remote_n_portd" #define CONFIG_STRING_L1_TRANSPORT_N_PREFERENCE "tr_n_preference" #define CONFIG_STRING_L1_PUSCH_PROC_THREADS "pusch_proc_threads" +#define CONFIG_STRING_L1_OFDM_OFFSET_DIVISOR "ofdm_offset_divisor" /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ /* L1 configuration parameters */ @@ -62,7 +63,8 @@ {CONFIG_STRING_L1_REMOTE_N_PORTC, NULL, 0, uptr:NULL, defintval:50030, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_LOCAL_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_REMOTE_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ -{CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:3, TYPE_UINT, 0} \ +{CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:3, TYPE_UINT, 0}, \ +{CONFIG_STRING_L1_OFDM_OFFSET_DIVISOR, NULL, 0, uptr:NULL, defuintval:UINT_MAX, TYPE_UINT, 0} \ } #define L1_CC_IDX 0 #define L1_TRANSPORT_N_PREFERENCE_IDX 1 @@ -74,6 +76,7 @@ #define L1_LOCAL_N_PORTD_IDX 7 #define L1_REMOTE_N_PORTD_IDX 8 #define L1_PUSCH_PROC_THREADS 9 +#define L1_OFDM_OFFSET_DIVISOR 10 /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index d3dd769807..fc811b2d11 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -591,6 +591,7 @@ void RCconfig_NR_L1(void) { } RC.gNB[j]->pusch_proc_threads = *(L1_ParamList.paramarray[j][L1_PUSCH_PROC_THREADS].uptr); + RC.gNB[j]->ofdm_offset_divisor = *(L1_ParamList.paramarray[j][L1_OFDM_OFFSET_DIVISOR].uptr); if(strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) { //sf_ahead = 2; // Need 4 subframe gap between RX and TX diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index 7080aff8ea..b53acbabdc 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -235,6 +235,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; } ); From f5913f3bfc0309dd01b793b405417a2dbe506479 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sun, 25 Apr 2021 21:45:49 +0200 Subject: [PATCH 066/185] Fixed bug in UL slot fep --- openair1/PHY/MODULATION/slot_fep_nr.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 2fe5901991..70fdc4b2c9 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -298,12 +298,13 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, // This is for misalignment issues int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); - unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - // offset of first OFDM symbol - int32_t rxdata_offset = slot_offset + nb_prefix_samples0; - // offset of n-th OFDM symbol - rxdata_offset += symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples); + unsigned int rxdata_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; + for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) + rxdata_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rxdata_offset += frame_parms->ofdm_symbol_size * symbol; + // use OFDM symbol from within 1/8th of the CP to avoid ISI rxdata_offset -= (nb_prefix_samples / frame_parms->ofdm_offset_divisor); From 33021bd826697f294d20a630c5572eeed69113d6 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 26 Apr 2021 13:32:02 +0200 Subject: [PATCH 067/185] Adding offset divisor parameter to all config files --- openair2/GNB_APP/L1_nr_paramdef.h | 2 +- .../GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf | 1 + .../GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf | 1 + .../GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf | 1 + .../CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf | 1 + .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf | 2 +- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf | 1 + .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf | 1 + .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf | 1 + .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf | 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf | 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf | 1 + .../GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf | 1 + .../GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 1 + 14 files changed, 14 insertions(+), 2 deletions(-) diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h index 2f58860161..34372f6011 100644 --- a/openair2/GNB_APP/L1_nr_paramdef.h +++ b/openair2/GNB_APP/L1_nr_paramdef.h @@ -64,7 +64,7 @@ {CONFIG_STRING_L1_LOCAL_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_REMOTE_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:3, TYPE_UINT, 0}, \ -{CONFIG_STRING_L1_OFDM_OFFSET_DIVISOR, NULL, 0, uptr:NULL, defuintval:UINT_MAX, TYPE_UINT, 0} \ +{CONFIG_STRING_L1_OFDM_OFFSET_DIVISOR, NULL, 0, uptr:NULL, defuintval:8, TYPE_UINT, 0} \ } #define L1_CC_IDX 0 #define L1_TRANSPORT_N_PREFERENCE_IDX 1 diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf index e1bf1b9818..5481b16e0d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf @@ -251,6 +251,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf index ceba30dacf..988fd02bbe 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf @@ -234,6 +234,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf index 115ed6f6f0..d957f0454f 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf @@ -234,6 +234,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf index ffced2055a..85d2a30e4d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf @@ -284,6 +284,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index b53acbabdc..05d51e334a 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -235,7 +235,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; - ofdm_offset_divisor = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf index 4039012fe1..9766462d04 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf @@ -235,6 +235,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf index 89dda14e20..a60303e600 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf @@ -235,6 +235,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf index 7954b3c201..3671fef0f2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf @@ -235,6 +235,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf index bd88ed88c7..4d88ca4b57 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf @@ -235,6 +235,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf index b2a765c447..bbed2d8a28 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf @@ -251,6 +251,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf index 185edc5666..ab7ab49983 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf @@ -251,6 +251,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf index 20423b50b9..a22b2fd193 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf @@ -255,6 +255,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index c4d9de3347..38aa035610 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -255,6 +255,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); From 4d60c5e4fd5e2dac994235bac21bae1fedae1b6e Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 26 Apr 2021 14:52:45 +0200 Subject: [PATCH 068/185] Fixing a bug --- openair1/PHY/MODULATION/slot_fep_nr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 70fdc4b2c9..bd8d89bdca 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -158,7 +158,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, frame_parms->ofdm_symbol_size, 15); - int16_t *shift_rot = frame_parms->timeshift_symbol_rotation[0]; + int16_t *shift_rot = frame_parms->timeshift_symbol_rotation[1]; multadd_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], shift_rot, @@ -367,7 +367,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, length, 15); - int16_t *shift_rot = frame_parms->timeshift_symbol_rotation[0]; + int16_t *shift_rot = frame_parms->timeshift_symbol_rotation[1]; multadd_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], shift_rot, From 626ab8aa3a3d3ad6521daa30c6170d9d51c7a203 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 26 Apr 2021 11:28:54 +0200 Subject: [PATCH 069/185] NR_UE: adjust some LOG levels --- openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 2 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 3f52b29281..a85076b623 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -180,7 +180,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, ue->measurements.wideband_cqi_avg[gNB_id] = dB_fixed2(ue->measurements.rx_power_avg[gNB_id], ue->measurements.n0_power_avg); ue->measurements.rx_rssi_dBm[gNB_id] = ue->measurements.rx_power_avg_dB[gNB_id] + 30 - 10*log10(pow(2, 30)) - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); - LOG_I(PHY, "[gNB %d] Slot %d, RSSI %d dBm/RE, RSSI (digital) %d dB, WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d \n", + LOG_D(PHY, "[gNB %d] Slot %d, RSSI %d dBm/RE, RSSI (digital) %d dB, WBandCQI %d dB, rxPwrAvg %d, n0PwrAvg %d \n", gNB_id, slot, ue->measurements.rx_rssi_dBm[gNB_id], diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 60fe897456..2b6c74577e 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -234,7 +234,7 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){ ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling; - LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n", + LOG_I(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n", __FUNCTION__, ue->Mod_id, frame_tx, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 78328e3888..0ef03cd2cd 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -101,7 +101,7 @@ int8_t nr_ue_decode_mib(module_id_t module_id, void *pduP, uint16_t cell_id) { - LOG_D(MAC,"[L2][MAC] decode mib\n"); + LOG_I(MAC,"[L2][MAC] decode mib\n"); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); NR_ServingCellConfigCommon_t *scc = mac->scc; @@ -1912,7 +1912,7 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, #endif */ - LOG_I(MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d\n", frameP, slot, ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); + LOG_D(MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d\n", frameP, slot, ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); break; case DL_SCH_LCID_CON_RES_ID: From 942037beb3fe5055b250e0560b83943fd2348456 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 26 Apr 2021 14:45:56 +0200 Subject: [PATCH 070/185] 5G NR: move CIR peak to 0 The rotation compensating the shifted OFDM position _before_ the channel estimation makes the CIR peak move back to 0. We have to take this into account on gNB side when calculating the timing advance command, and on UE side in the time adjustment. --- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 17 ++- .../PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c | 116 +++++++++--------- 2 files changed, 65 insertions(+), 68 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 36e1c3fee9..ca5108ef45 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -39,20 +39,20 @@ extern openair0_config_t openair0_cfg[MAX_CARDS]; int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) { - int i, aa, max_pos = 0, max_val = 0; - + int max_pos = 0, max_val = 0; + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; - - int sync_pos = frame_parms->nb_prefix_samples / frame_parms->ofdm_offset_divisor; - for (i = 0; i < frame_parms->ofdm_symbol_size; i++) { + const int sync_pos = 0; + + for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { int temp = 0; - for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - short Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; - short Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + int Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; + int Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; temp += (Re*Re/2) + (Im*Im/2); } @@ -65,7 +65,6 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) if (max_pos > frame_parms->ofdm_symbol_size/2) max_pos = max_pos - frame_parms->ofdm_symbol_size; - return max_pos - sync_pos; } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index f411e8d5b2..4cebeab712 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -45,25 +45,23 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, 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; + int max_val = 0, max_pos = 0; + const int sync_pos = 0; uint8_t sync_offset = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); - ncoef = 32767 - coef; + short ncoef = 32767 - coef; LOG_D(PHY,"AbsSubframe %d: rx_offset (before) = %d\n",subframe,ue->rx_offset); - // we only use channel estimates from tx antenna 0 here - for (i = 0; i < frame_parms->nb_prefix_samples; i++) { - temp = 0; + for (int i = 0; i < frame_parms->nb_prefix_samples; i++) { + int temp = 0; - for (aa=0; aanb_antennas_rx; aa++) { - Re = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[(i<<1)]; - Im = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[1+(i<<1)]; + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + int Re = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[(i<<1)]; + int Im = ((int16_t*)ue->pbch_vars[gNB_id]->dl_ch_estimates_time[aa])[1+(i<<1)]; temp += (Re*Re/2) + (Im*Im/2); } @@ -73,6 +71,9 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, } } + if (max_pos > frame_parms->ofdm_symbol_size/2) + max_pos = max_pos - frame_parms->ofdm_symbol_size; + // filter position to reduce jitter if (clear == 1) max_pos_fil = max_pos; @@ -82,61 +83,58 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, // do not filter to have proactive timing adjustment //max_pos_fil = max_pos; - diff = max_pos_fil - (frame_parms->nb_prefix_samples / frame_parms->ofdm_offset_divisor); + int diff = max_pos_fil - sync_pos; - if (frame_parms->freq_range==nr_FR2) - sync_offset = 2; - else - sync_offset = 0; - - if ( abs(diff) < (SYNCH_HYST+sync_offset) ) - ue->rx_offset = 0; - else - ue->rx_offset = diff; + if (frame_parms->freq_range==nr_FR2) + sync_offset = 2; + else + sync_offset = 0; - 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 ( abs(diff) < (SYNCH_HYST+sync_offset) ) + ue->rx_offset = 0; + else + ue->rx_offset = diff; - if(count_max_pos_ok > 10 && first_time == 1) - { - first_time = 0; - ue->time_sync_cell = 1; - if (get_softmodem_params()->do_ra) { - LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); - //mac_resynch(); - //dl_phy_sync_success(ue->Mod_id,frame,0,1);//ue->common_vars.eNb_id); - ue->UE_mode[0] = PRACH; - ue->prach_resources[gNB_id]->sync_frame = frame; - ue->prach_resources[gNB_id]->init_msg1 = 0; - } else { - ue->UE_mode[0] = PUSCH; - } - } + 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 (ue->rx_offset < 0) - ue->rx_offset += frame_parms->samples_per_frame; + if(count_max_pos_ok > 10 && first_time == 1) + { + first_time = 0; + ue->time_sync_cell = 1; + if (get_softmodem_params()->do_ra) { + LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); + //mac_resynch(); + //dl_phy_sync_success(ue->Mod_id,frame,0,1);//ue->common_vars.eNb_id); + ue->UE_mode[0] = PRACH; + ue->prach_resources[gNB_id]->sync_frame = frame; + ue->prach_resources[gNB_id]->init_msg1 = 0; + } else { + ue->UE_mode[0] = PUSCH; + } + } - if (ue->rx_offset >= frame_parms->samples_per_frame) - ue->rx_offset -= frame_parms->samples_per_frame; + if (ue->rx_offset < 0) + ue->rx_offset += frame_parms->samples_per_frame; + if (ue->rx_offset >= frame_parms->samples_per_frame) + ue->rx_offset -= frame_parms->samples_per_frame; +#ifdef DEBUG_PHY + LOG_D(PHY,"AbsSubframe %d: diff = %i, rx_offset (final) = %i : clear = %d, max_pos = %d, max_pos_fil = %d, max_val = %d, sync_pos %d\n", + subframe, + diff, + ue->rx_offset, + clear, + max_pos, + max_pos_fil, + max_val, + sync_pos); +#endif //DEBUG_PHY - #ifdef DEBUG_PHY - LOG_D(PHY,"AbsSubframe %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", - 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); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); } From 5c6865fbc6d093ed9b836c318df35eaa9ff0eec5 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 26 Apr 2021 16:09:32 +0200 Subject: [PATCH 071/185] 5G NR: simplify init_timeshift_rotation() Only Ncp1 is used, so get rid of the second timeshift_symbol_rotation array. Also simplify the computation of "t0 * Tc * f". --- openair1/PHY/MODULATION/nr_modulation.c | 67 +++---------------------- openair1/PHY/MODULATION/slot_fep_nr.c | 4 +- openair1/PHY/defs_nr_common.h | 2 +- 3 files changed, 11 insertions(+), 62 deletions(-) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index d38373afff..c81a88ff30 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -747,69 +747,18 @@ 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 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 / fp->ofdm_offset_divisor; - 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 / fp->ofdm_offset_divisor; - 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); + for (int i = 0; i < fp->ofdm_symbol_size; i++) { + double poff = -i * 2.0 * M_PI * 144.0 / 2048.0 / fp->ofdm_offset_divisor; + double exp_re = cos(poff); + double exp_im = sin(-poff); + fp->timeshift_symbol_rotation[i*2] = (int16_t)round(exp_re * 32767); + fp->timeshift_symbol_rotation[i*2+1] = (int16_t)round(exp_im * 32767); if (i < 10) LOG_I(PHY,"Timeshift symbol rotation %d => (%d,%d) %f\n",i, - fp->timeshift_symbol_rotation[0][i*2], - fp->timeshift_symbol_rotation[0][i*2+1], + fp->timeshift_symbol_rotation[i*2], + fp->timeshift_symbol_rotation[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 / fp->ofdm_offset_divisor; - poff = 2 * M_PI * -t0 * Tc * f; - exp_re = cos(poff); - exp_im = sin(-poff); - timeshift_symbol_rotation[j*2] = (int16_t)ceil(exp_re * 32767); - timeshift_symbol_rotation[j*2+1] = (int16_t)ceil(exp_im * 32767); - - timeshift_symbol_rotation = fp->timeshift_symbol_rotation[1]; - t0 = Ncp1 / fp->ofdm_offset_divisor; - poff = 2 * M_PI * -t0 * Tc * f; - exp_re = cos(poff); - exp_im = sin(-poff); - timeshift_symbol_rotation[j*2] = (int16_t)ceil(exp_re * 32767); - timeshift_symbol_rotation[j*2+1] = (int16_t)ceil(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[0][j*2], - fp->timeshift_symbol_rotation[0][j*2+1], - poff); - i++; } } diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index bd8d89bdca..f0abd52c7f 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -158,7 +158,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, frame_parms->ofdm_symbol_size, 15); - int16_t *shift_rot = frame_parms->timeshift_symbol_rotation[1]; + int16_t *shift_rot = frame_parms->timeshift_symbol_rotation; multadd_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], shift_rot, @@ -367,7 +367,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, length, 15); - int16_t *shift_rot = frame_parms->timeshift_symbol_rotation[1]; + int16_t *shift_rot = frame_parms->timeshift_symbol_rotation; multadd_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], shift_rot, diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index f89c3d66af..0b729302a9 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -331,7 +331,7 @@ struct NR_DL_FRAME_PARMS { 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))); + int16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16))); /// shift of pilot position in one RB uint8_t nushift; /// SRS configuration from TS 38.331 RRC From b073ca48c3639af235ec9be149560565b5441d4f Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 26 Apr 2021 17:25:54 +0200 Subject: [PATCH 072/185] gNB: improve TA accuracy The TA calculation takes the CIR peak position error and scales it according to 38.213 section 4.2. Till now it was simply an integer division "timing_advance_update = sync_pos / bw_scaling". E.g. in case of bandwidth_scaling == 16, the timing_advance_update was 0 for sync_pos between -15 and +15. With this change, this range (and thus the UL timing error) will be reduced to -8 and +8. --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index d44c8641a6..03625f87cf 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -369,6 +369,11 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; + // do some integer rounding to improve TA accuracy + if (sync_pos > 0) + sync_pos += bw_scaling / 2 - 1; + else if(sync_pos < 0) + sync_pos -= bw_scaling / 2 - 1; timing_advance_update = sync_pos / bw_scaling; // put timing advance command in 0..63 range From 7edb2351022a2d0b20c7bc6378d5b6f380fedb8c Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 26 Apr 2021 22:47:19 +0200 Subject: [PATCH 073/185] Updating gnb config files --- ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf | 7 ++++--- ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf | 1 + .../conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf | 1 + .../CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf | 6 ++++-- .../CONF/gnb.band257.tm1.32PRB.usrpn300.conf | 6 ++++-- .../CONF/gnb.band257.tm1.32PRB.usrpx300.conf | 6 ++++-- .../CONF/gnb.band257.tm1.66PRB.usrpn300.conf | 6 ++++-- .../GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf | 6 ++++-- .../CONF/gnb.band78.tm1.106PRB.usrpb210.conf | 6 ++++-- .../CONF/gnb.band78.tm1.217PRB.usrpn300.conf | 6 ++++-- .../CONF/gnb.band78.tm1.217PRB.usrpx300.conf | 6 ++++-- .../CONF/gnb.band78.tm1.273PRB.usrpn300.conf | 6 ++++-- 12 files changed, 42 insertions(+), 21 deletions(-) diff --git a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf index 0da833b3f7..9672a60dd3 100644 --- a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf @@ -248,9 +248,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 8; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf index b8a601ce41..f174381a2e 100644 --- a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf @@ -234,6 +234,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf index 7be25a24fa..e8d0bf2ca1 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -252,6 +252,7 @@ L1s = ( num_cc = 1; tr_n_preference = "local_mac"; pusch_proc_threads = 6; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf index 5fd4b465b3..10241eb9b5 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf @@ -238,8 +238,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf index 477240a3a0..7d268f23f2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpn300.conf @@ -248,8 +248,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf index 8b1079350b..8317d36548 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf @@ -234,8 +234,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf index 3bfcc01703..794767f193 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf @@ -222,8 +222,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf index 27ade965dc..ecdd256ce9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf @@ -249,8 +249,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf index b517bea8ee..81bcbab591 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf @@ -222,8 +222,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf index 20e8aabf98..e90a4739f3 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf @@ -248,8 +248,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf index fc8bda5d53..3573e5d002 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf @@ -227,8 +227,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf index 694b78e08d..c8e0a3b836 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf @@ -232,8 +232,10 @@ MACRLCs = ( L1s = ( { - num_cc = 1; - tr_n_preference = "local_mac"; + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 } ); From 8a7a79374bae4bd3c424573c23901141086b8624 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 27 Apr 2021 17:08:13 +0200 Subject: [PATCH 074/185] 5G NR: change PUSCH and PDSCH channel levelling for higher accuracy --- openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index c1bca8d2a0..dbdb557627 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1272,7 +1272,7 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, for (aarx=0;aarxnb_antennas_rx;aarx++) avgs = cmax(avgs,avg[(aatx<<1)+aarx]); - gNB->pusch_vars[ulsch_id]->log2_maxh = (log2_approx(avgs)/2)+3; + gNB->pusch_vars[ulsch_id]->log2_maxh = (log2_approx(avgs)/2) + 1; gNB->pusch_vars[ulsch_id]->cl_done = 1; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 35baef1792..5fd784ce2d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -443,8 +443,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //LOG_I(PHY, "avgs Power per SC is %d\n", avgs); median[(aatx*frame_parms->nb_antennas_rx)+aarx] = avg[(aatx*frame_parms->nb_antennas_rx)+aarx]; } - pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2)+3; - //LOG_I(PHY, "avgs Power per SC is %d lg2_maxh %d\n", avgs, pdsch_vars[gNB_id]->log2_maxh); if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { nr_dlsch_channel_level_median(pdsch_vars[gNB_id]->dl_ch_estimates_ext, @@ -459,8 +457,10 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, avgs = cmax(avgs, median[aatx*n_rx + aarx]); } } - pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; } + + pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; + //LOG_I(PHY, "avgs Power per SC is %d lg2_maxh %d\n", avgs, pdsch_vars[gNB_id]->log2_maxh); } LOG_D(PHY,"[DLSCH] AbsSubframe %d.%d log2_maxh = %d [log2_maxh0 %d log2_maxh1 %d] (%d,%d)\n", frame%1024, From 4c6cf19364a3d46069d7e2f890fec8e8fe569a69 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 27 Apr 2021 18:17:40 +0200 Subject: [PATCH 075/185] bugfix for sib1 in case of ssb different from 0 again --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 4 ++++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 4cd493813a..a932551557 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -428,6 +428,10 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, scc, NULL); + pdcch_pdu_rel15->BWPSize = type0_PDCCH_CSS_config->num_rbs; + pdcch_pdu_rel15->BWPStart = type0_PDCCH_CSS_config->cset_start_rb; + pdcch_pdu_rel15->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch; + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index cb4c10c5dd..bbe0f62f9c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -605,9 +605,6 @@ void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, sps = bwp->bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; } else { - pdcch_pdu->BWPSize = gNB_mac->type0_PDCCH_CSS_config->num_rbs; - pdcch_pdu->BWPStart = gNB_mac->type0_PDCCH_CSS_config->cset_start_rb; - pdcch_pdu->SubcarrierSpacing = gNB_mac->type0_PDCCH_CSS_config->scs_pdcch; pdcch_pdu->CyclicPrefix = 0; sps = 14; } From be9fe071d286e0bb04182f76bdf0a40eaa535a5c Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Wed, 28 Apr 2021 16:18:03 +0100 Subject: [PATCH 076/185] Fix dmrs_idx for coreset with duration > 1 symbol --- openair1/PHY/NR_TRANSPORT/nr_dci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index cf38aaa4bf..9d3ee61ad1 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -197,9 +197,9 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - dmrs_idx =gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx * 3; + dmrs_idx =(gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx / pdcch_pdu_rel15->DurationSymbols) * 3; else - dmrs_idx = (gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx + rb_offset) * 3; + dmrs_idx = (gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx / pdcch_pdu_rel15->DurationSymbols + rb_offset) * 3; k_prime = 0; From 493dab700dc926a6956f7f1c6b0f1f69428c2c42 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 29 Apr 2021 15:29:43 +0200 Subject: [PATCH 077/185] Updating ulsim adding option to change numberology --- openair1/SIMULATION/NR_PHY/ulsim.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index ee018ce871..3498938fca 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -234,7 +234,7 @@ int main(int argc, char **argv) //int8_t interf1 = -21, interf2 = -21; FILE *input_fd = NULL; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; - uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; + uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 3; NB_UE_INST = 1; @@ -298,7 +298,7 @@ int main(int argc, char **argv) /* initialize the sin-cos table */ InitSinLUT(); - while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:ikl:m:n:p:r:s:y:z:F:G:H:M:N:PR:S:T:U:L:Z")) != -1) { + while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:ikl:m:n:p:r:s:u:w:y:z:F:G:H:M:N:PR:S:T:U:L:Z")) != -1) { printf("handling optarg %c\n",c); switch (c) { @@ -424,6 +424,14 @@ int main(int argc, char **argv) printf("Setting SNR0 to %f\n", snr0); break; + case 'u': + mu = atoi(optarg); + break; + + case 'w': + start_rb = atoi(optarg); + break; + /* case 't': eff_tp_check = (float)atoi(optarg)/100; @@ -552,6 +560,8 @@ int main(int argc, char **argv) printf("-n Number of trials to simulate\n"); printf("-p Use extended prefix mode\n"); printf("-t Delay spread for multipath channel\n"); + printf("-u Set the numerology\n"); + printf("-w Start PRB for PUSCH\n"); //printf("-x Transmission mode (1,2,6 for the moment)\n"); printf("-y Number of TX antennas used in eNB\n"); printf("-z Number of RX antennas used in UE\n"); @@ -592,10 +602,12 @@ int main(int argc, char **argv) if (N_RB_UL >= 217) sampling_frequency = 122.88; else if (N_RB_UL >= 106) sampling_frequency = 61.44; + else if (N_RB_UL >= 32) sampling_frequency = 32.72; else { printf("Need at least 106 PRBs\b"); exit(-1); } if (N_RB_UL == 273) bandwidth = 100; else if (N_RB_UL == 217) bandwidth = 80; else if (N_RB_UL == 106) bandwidth = 40; + else if (N_RB_UL == 32) bandwidth = 50; else { printf("Add N_RB_UL %d\n",N_RB_UL); exit(-1); } if (openair0_cfg[0].threequarter_fs == 1) sampling_frequency*=.75; From 04b46effc26f78080edb52cb3a2d65fa9abd6cca Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 30 Apr 2021 16:34:35 +0200 Subject: [PATCH 078/185] Disabling the DC clearing in UL --- openair1/PHY/MODULATION/slot_fep_nr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index f0abd52c7f..6de53e3529 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -340,9 +340,6 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - // clear DC carrier from OFDM symbols - rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0; - return 0; } From 2b96ebac1f0c44af0ca785aac705efda4267d74a Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 30 Apr 2021 16:48:06 +0200 Subject: [PATCH 079/185] Changing back the default numnerology --- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 3498938fca..bdb24adcc3 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -234,7 +234,7 @@ int main(int argc, char **argv) //int8_t interf1 = -21, interf2 = -21; FILE *input_fd = NULL; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; - uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 3; + uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; NB_UE_INST = 1; From 4a00aa25ef1cf2b5f308e2d014989fa39c54e305 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 30 Apr 2021 18:56:43 +0200 Subject: [PATCH 080/185] improvements in pdsch allocation for sib1 --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 346 +++++++++++------- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 7 + openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h | 9 - openair2/LAYER2/NR_MAC_UE/mac_proto.h | 1 + openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 35 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 93 +++-- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 16 +- 8 files changed, 285 insertions(+), 224 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 4ce9b1b140..bb3d4e4b36 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -126,151 +126,225 @@ const float table_38213_13_12_c3[16] = { 1, 0.5f, 1, 0.5f, 1, 0.5f, 0.5f, 0.5f const int32_t table_38213_10_1_1_c2[5] = { 0, 0, 4, 2, 1 }; // for PDSCH from TS 38.214 subclause 5.1.2.1.1 -const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[16][3]={ - {0,2,12}, // row index 1 - {0,2,10}, // row index 2 - {0,2,9}, // row index 3 - {0,2,7}, // row index 4 - {0,2,5}, // row index 5 - {0,9,4}, // row index 6 - {0,4,4}, // row index 7 - {0,5,7}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,12,2}, // row index 11 - {0,1,13}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,7}, // row index 15 - {0,8,4} // row index 16 +const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[16][4]={ + {1,0,2,12}, // row index 1 + {1,0,2,10}, // row index 2 + {1,0,2,9}, // row index 3 + {1,0,2,7}, // row index 4 + {1,0,2,5}, // row index 5 + {0,0,9,4}, // row index 6 + {0,0,4,4}, // row index 7 + {0,0,5,7}, // row index 8 + {0,0,5,2}, // row index 9 + {0,0,9,2}, // row index 10 + {0,0,12,2}, // row index 11 + {1,0,1,13}, // row index 12 + {1,0,1,6}, // row index 13 + {1,0,2,4}, // row index 14 + {0,0,4,7}, // row index 15 + {0,0,8,4} // row index 16 }; -const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[16][3]={ - {0,3,11}, // row index 1 - {0,3,9}, // row index 2 - {0,3,8}, // row index 3 - {0,3,6}, // row index 4 - {0,3,4}, // row index 5 - {0,10,4}, // row index 6 - {0,6,4}, // row index 7 - {0,5,7}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,12,2}, // row index 11 - {0,1,13}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,7}, // row index 15 - {0,8,4} // row index 16 +const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[16][4]={ + {1,0,3,11}, // row index 1 + {1,0,3,9}, // row index 2 + {1,0,3,8}, // row index 3 + {1,0,3,6}, // row index 4 + {1,0,3,4}, // row index 5 + {0,0,10,4}, // row index 6 + {0,0,6,4}, // row index 7 + {0,0,5,7}, // row index 8 + {0,0,5,2}, // row index 9 + {0,0,9,2}, // row index 10 + {0,0,12,2}, // row index 11 + {1,0,1,13}, // row index 12 + {1,0,1,6}, // row index 13 + {1,0,2,4}, // row index 14 + {0,0,4,7}, // row index 15 + {0,0,8,4} // row index 16 }; -const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[16][3]={ - {0,2,6}, // row index 1 - {0,2,10}, // row index 2 - {0,2,9}, // row index 3 - {0,2,7}, // row index 4 - {0,2,5}, // row index 5 - {0,6,4}, // row index 6 - {0,4,4}, // row index 7 - {0,5,6}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,10,2}, // row index 11 - {0,1,11}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,6}, // row index 15 - {0,8,4} // row index 16 +const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[16][4]={ + {1,0,2,6}, // row index 1 + {1,0,2,10}, // row index 2 + {1,0,2,9}, // row index 3 + {1,0,2,7}, // row index 4 + {1,0,2,5}, // row index 5 + {0,0,6,4}, // row index 6 + {0,0,4,4}, // row index 7 + {0,0,5,6}, // row index 8 + {0,0,5,2}, // row index 9 + {0,0,9,2}, // row index 10 + {0,0,10,2}, // row index 11 + {1,0,1,11}, // row index 12 + {1,0,1,6}, // row index 13 + {1,0,2,4}, // row index 14 + {0,0,4,6}, // row index 15 + {0,0,8,4} // row index 16 }; -const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[16][3]={ - {0,3,5}, // row index 1 - {0,3,9}, // row index 2 - {0,3,8}, // row index 3 - {0,3,6}, // row index 4 - {0,3,4}, // row index 5 - {0,8,2}, // row index 6 - {0,6,4}, // row index 7 - {0,5,6}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,10,2}, // row index 11 - {0,1,11}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,6}, // row index 15 - {0,8,4} // row index 16 +const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[16][4]={ + {1,0,3,5}, // row index 1 + {1,0,3,9}, // row index 2 + {1,0,3,8}, // row index 3 + {1,0,3,6}, // row index 4 + {1,0,3,4}, // row index 5 + {0,0,8,2}, // row index 6 + {0,0,6,4}, // row index 7 + {0,0,5,6}, // row index 8 + {0,0,5,2}, // row index 9 + {0,0,9,2}, // row index 10 + {0,0,10,2}, // row index 11 + {1,0,1,11}, // row index 12 + {1,0,1,6}, // row index 13 + {1,0,2,4}, // row index 14 + {0,0,4,6}, // row index 15 + {0,0,8,4} // row index 16 }; -const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[16][3]={ - {0,2,2}, // row index 1 - {0,4,2}, // row index 2 - {0,6,2}, // row index 3 - {0,8,2}, // row index 4 - {0,10,2}, // row index 5 - {1,2,2}, // row index 6 - {1,4,2}, // row index 7 - {0,2,4}, // row index 8 - {0,4,4}, // row index 9 - {0,6,4}, // row index 10 - {0,8,4}, // row index 11 - {0,10,4}, // row index 12 - {0,2,7}, // row index 13 - {0,2,12}, // row index 14 - {1,2,4}, // row index 15 - {0,0,0} // row index 16 +const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[16][4]={ + {0,0,2,2}, // row index 1 + {0,0,4,2}, // row index 2 + {0,0,6,2}, // row index 3 + {0,0,8,2}, // row index 4 + {0,0,10,2}, // row index 5 + {0,1,2,2}, // row index 6 + {0,1,4,2}, // row index 7 + {0,0,2,4}, // row index 8 + {0,0,4,4}, // row index 9 + {0,0,6,4}, // row index 10 + {0,0,8,4}, // row index 11 + {0,0,10,4}, // row index 12 + {0,0,2,7}, // row index 13 + {1,0,2,12}, // row index 14 + {0,1,2,4}, // row index 15 + {0,0,0,0} // row index 16 }; -const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[16][3]={ - {0,2,2}, // row index 1 - {0,4,2}, // row index 2 - {0,6,2}, // row index 3 - {0,8,2}, // row index 4 - {0,10,2}, // row index 5 - {1,2,2}, // row index 6 - {1,4,2}, // row index 7 - {0,2,4}, // row index 8 - {0,4,4}, // row index 9 - {0,6,4}, // row index 10 - {0,8,4}, // row index 11 - {0,10,4}, // row index 12 - {0,2,7}, // row index 13 - {0,3,11}, // row index 14 - {1,2,4}, // row index 15 - {0,0,0} // row index 16 +const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[16][4]={ + {0,0,2,2}, // row index 1 + {0,0,4,2}, // row index 2 + {0,0,6,2}, // row index 3 + {0,0,8,2}, // row index 4 + {0,0,10,2}, // row index 5 + {0,1,2,2}, // row index 6 + {0,1,4,2}, // row index 7 + {0,0,2,4}, // row index 8 + {0,0,4,4}, // row index 9 + {0,0,6,4}, // row index 10 + {0,0,8,4}, // row index 11 + {0,0,10,4}, // row index 12 + {0,0,2,7}, // row index 13 + {1,0,3,11}, // row index 14 + {0,1,2,4}, // row index 15 + {0,0,0,0} // row index 16 }; -const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[16][3]={ - {0,2,2}, // row index 1 - {0,4,2}, // row index 2 - {0,6,2}, // row index 3 - {0,8,2}, // row index 4 - {0,10,2}, // row index 5 - {0,0,0}, // row index 6 - {0,0,0}, // row index 7 - {0,2,4}, // row index 8 - {0,4,4}, // row index 9 - {0,6,4}, // row index 10 - {0,8,4}, // row index 11 - {0,10,4}, // row index 12 - {0,2,7}, // row index 13 - {0,2,12}, // row index 14 - {0,0,6}, // row index 15 - {0,2,6} // row index 16 +const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[16][4]={ + {0,0,2,2}, // row index 1 + {0,0,4,2}, // row index 2 + {0,0,6,2}, // row index 3 + {0,0,8,2}, // row index 4 + {0,0,10,2}, // row index 5 + {0,0,0,0}, // row index 6 + {0,0,0,0}, // row index 7 + {0,0,2,4}, // row index 8 + {0,0,4,4}, // row index 9 + {0,0,6,4}, // row index 10 + {0,0,8,4}, // row index 11 + {0,0,10,4}, // row index 12 + {0,0,2,7}, // row index 13 + {1,0,2,12}, // row index 14 + {1,0,0,6}, // row index 15 + {1,0,2,6} // row index 16 }; -const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[16][3]={ - {0,2,2}, // row index 1 - {0,4,2}, // row index 2 - {0,6,2}, // row index 3 - {0,8,2}, // row index 4 - {0,10,2}, // row index 5 - {0,0,0}, // row index 6 - {0,0,0}, // row index 7 - {0,2,4}, // row index 8 - {0,4,4}, // row index 9 - {0,6,4}, // row index 10 - {0,8,4}, // row index 11 - {0,10,4}, // row index 12 - {0,2,7}, // row index 13 - {0,3,11}, // row index 14 - {0,0,6}, // row index 15 - {0,2,6} // row index 16 +const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[16][4]={ + {0,0,2,2}, // row index 1 + {0,0,4,2}, // row index 2 + {0,0,6,2}, // row index 3 + {0,0,8,2}, // row index 4 + {0,0,10,2}, // row index 5 + {0,0,0,0}, // row index 6 + {0,0,0,0}, // row index 7 + {0,0,2,4}, // row index 8 + {0,0,4,4}, // row index 9 + {0,0,6,4}, // row index 10 + {0,0,8,4}, // row index 11 + {0,0,10,4}, // row index 12 + {0,0,2,7}, // row index 13 + {1,0,3,11}, // row index 14 + {1,0,0,6}, // row index 15 + {1,0,2,6} // row index 16 }; +void get_info_from_tda_tables(int default_abc, + int tda, + int dmrs_TypeA_Position, + int normal_CP, + int *startSymbolIndex, + int *nrOfSymbols) { + int k0 = 0; + int is_mapping_typeA = 1; + switch(default_abc){ + case 1: + if (normal_CP){ + if (dmrs_TypeA_Position){ + is_mapping_typeA = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][0]; + k0 = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][1]; + *startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][2]; + *nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[tda][3]; + } + else{ + is_mapping_typeA = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][0]; + k0 = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][1]; + *startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][2]; + *nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[tda][3]; + } + } + else{ + if (dmrs_TypeA_Position){ + is_mapping_typeA = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][0]; + k0 = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][1]; + *startSymbolIndex = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][2]; + *nrOfSymbols = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[tda][3]; + } + else{ + is_mapping_typeA = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][0]; + k0 = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][1]; + *startSymbolIndex = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][2]; + *nrOfSymbols = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[tda][3]; + } + } + break; + case 2: + if (dmrs_TypeA_Position){ + is_mapping_typeA = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][0]; + k0 = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][1]; + *startSymbolIndex = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][2]; + *nrOfSymbols = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[tda][3]; + } + else{ + is_mapping_typeA = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][0]; + k0 = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][1]; + *startSymbolIndex = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][2]; + *nrOfSymbols = table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[tda][3]; + } + break; + case 3: + if (dmrs_TypeA_Position){ + is_mapping_typeA = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][0]; + k0 = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][1]; + *startSymbolIndex = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][2]; + *nrOfSymbols = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[tda][3]; + } + else{ + is_mapping_typeA = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][0]; + k0 = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][1]; + *startSymbolIndex = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][2]; + *nrOfSymbols = table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[tda][3]; + } + break; + default: + AssertFatal(1==0,"Invalid default time domaing allocation type\n"); + } + AssertFatal(k0==0,"Only k0 = 0 is supported\n"); + AssertFatal(is_mapping_typeA==1,"Only mapping type A is currently supported\n"); +} + const char *prachfmt[]={"0","1","2","3", "A1","A2","A3","B1","B4","C0","C2","A1/B1","A2/B2","A3/B3"}; const char *duplex_mode[]={"FDD","TDD"}; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 0470abe355..b83dd70260 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -140,6 +140,13 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD uint16_t get_ssb_start_symbol(const long band, NR_SubcarrierSpacing_t scs, int i_ssb); +void get_info_from_tda_tables(int default_abc, + int tda, + int dmrs_TypeA_Position, + int normal_CP, + int *startSymbolIndex, + int *nrOfSymbols); + void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); uint8_t fill_searchSpaceZero(NR_SearchSpace_t *ss0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, int L); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h index 1e0ab98d4c..8f7a726bb8 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h @@ -139,13 +139,4 @@ extern const float table_38213_13_12_c3[16]; extern const int32_t table_38213_10_1_1_c2[5]; -extern const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[16][3]; -extern const uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[16][3]; -extern const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos2[16][3]; -extern const uint8_t table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP_dmrs_typeA_pos3[16][3]; -extern const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos2[16][3]; -extern const uint8_t table_5_1_2_1_1_4_time_dom_res_alloc_B_dmrs_typeA_pos3[16][3]; -extern const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos2[16][3]; -extern const uint8_t table_5_1_2_1_1_5_time_dom_res_alloc_C_dmrs_typeA_pos3[16][3]; - #endif //DEF_H diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 0f0e787c2e..0e0bc66cce 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -182,6 +182,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, uint8_t time_domain_ind, + int default_abc, bool use_default); uint8_t nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 8fbb94d45c..c292f97746 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -268,13 +268,14 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, uint8_t time_domain_ind, + int default_abc, bool use_default){ int dmrs_typeA_pos = (mac->scc != NULL) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position; // uint8_t k_offset=0; - uint8_t sliv_S=0; - uint8_t sliv_L=0; + int sliv_S=0; + int sliv_L=0; uint8_t mu_pusch = 1; // definition table j Table 6.1.2.1.1-4 @@ -349,25 +350,14 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, } else {// Default configuration from tables -// k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0]; - if(dmrs_typeA_pos == 0) { - sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[time_domain_ind][1]; - sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[time_domain_ind][2]; - } else { - sliv_S = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[time_domain_ind][1]; - sliv_L = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[time_domain_ind][2]; - } + get_info_from_tda_tables(default_abc, + time_domain_ind, + dmrs_typeA_pos, + 1, // normal CP + &sliv_S, + &sliv_L); - // k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0]; - // sliv_S = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][1]; - // sliv_L = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][2]; - // k_offset = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][0]; - // sliv_S = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][1]; - // sliv_L = table_5_1_2_1_1_4_time_dom_res_alloc_B[nr_pdci_info_extracted->time_dom_resource_assignment][2]; - // k_offset = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][0]; - // sliv_S = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][1]; - // sliv_L = table_5_1_2_1_1_5_time_dom_res_alloc_C[nr_pdci_info_extracted->time_dom_resource_assignment][2]; dlsch_config_pdu->number_symbols = sliv_L; dlsch_config_pdu->start_symbol = sliv_S; } @@ -449,6 +439,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr RA_config_t *ra = &mac->ra; fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; uint8_t is_Msg3 = 0; + int default_abc = 1; uint16_t n_RB_DLBWP; if (mac->DLbwp[0]) n_RB_DLBWP = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); @@ -624,6 +615,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr uint16_t BWPSize = 0; if(rnti == SI_RNTI) { + NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config = mac->type0_PDCCH_CSS_config; + default_abc = type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH; dlsch_config_pdu_1_0->BWPSize = mac->type0_PDCCH_CSS_config.num_rbs; dlsch_config_pdu_1_0->BWPStart = mac->type0_PDCCH_CSS_config.cset_start_rb; @@ -673,7 +666,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr return -1; } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val,rnti==SI_RNTI) < 0) { + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val,default_abc,rnti==SI_RNTI) < 0) { LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; } @@ -864,7 +857,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr return -1; } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val,false) < 0) { + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val,0,false) < 0) { LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index dcc88b5e29..c30e7dae81 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -709,7 +709,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, return -1; } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac, pusch_config_pdu, NULL, dci->time_domain_assignment.val,false) < 0) { + if (nr_ue_process_dci_time_dom_resource_assignment(mac, pusch_config_pdu, NULL, dci->time_domain_assignment.val,0,false) < 0) { return -1; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index a932551557..0a4f053817 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -309,14 +309,14 @@ void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart } -void schedule_control_sib1(module_id_t module_id, - int CC_id, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - uint8_t mcsTableIdx, - uint8_t mcs, - uint8_t candidate_idx, - int num_total_bytes) { +uint32_t schedule_control_sib1(module_id_t module_id, + int CC_id, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + int time_domain_allocation, + int startSymbolIndex, + int nrOfSymbols, + uint8_t candidate_idx, + int num_total_bytes) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; @@ -336,8 +336,8 @@ void schedule_control_sib1(module_id_t module_id, } gNB_mac->sched_ctrlCommon->time_domain_allocation = time_domain_allocation; - gNB_mac->sched_ctrlCommon->mcsTableIdx = mcsTableIdx; - gNB_mac->sched_ctrlCommon->mcs = mcs; + gNB_mac->sched_ctrlCommon->mcsTableIdx = 0; + gNB_mac->sched_ctrlCommon->mcs = 0; // starting from mcs 0 gNB_mac->sched_ctrlCommon->num_total_bytes = num_total_bytes; uint8_t nr_of_candidates; @@ -356,16 +356,6 @@ void schedule_control_sib1(module_id_t module_id, const uint16_t bwpSize = type0_PDCCH_CSS_config->num_rbs; int rbStart = type0_PDCCH_CSS_config->cset_start_rb; - int startSymbolIndex = 0; - int nrOfSymbols = 0; - if(gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position == 0) { - startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->time_domain_allocation][1]; - nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->time_domain_allocation][2]; - } else { - startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->time_domain_allocation][1]; - nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->time_domain_allocation][2]; - } - if (nrOfSymbols == 2) { gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData = 1; } else { @@ -383,25 +373,37 @@ void schedule_control_sib1(module_id_t module_id, int rbSize = 0; uint32_t TBS = 0; do { - rbSize++; + if(rbSize < bwpSize && !vrb_map[rbStart + rbSize]) + rbSize++; + else{ + if (gNB_mac->sched_ctrlCommon->mcs<10) + gNB_mac->sched_ctrlCommon->mcs++; + else + break; + } TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3; - } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes); + } while (TBS < gNB_mac->sched_ctrlCommon->num_total_bytes); + + AssertFatal(TBS>=gNB_mac->sched_ctrlCommon->num_total_bytes,"Couldn't allocate enough resources for %d bytes in SIB1 PDSCH\n", + gNB_mac->sched_ctrlCommon->num_total_bytes); gNB_mac->sched_ctrlCommon->rbSize = rbSize; gNB_mac->sched_ctrlCommon->rbStart = 0; - LOG_D(MAC,"startSymbolIndex = %i\n", startSymbolIndex); - LOG_D(MAC,"nrOfSymbols = %i\n", nrOfSymbols); - LOG_D(MAC,"rbSize = %i\n", gNB_mac->sched_ctrlCommon->rbSize); - LOG_D(MAC,"TBS = %i\n", TBS); - LOG_D(MAC,"dmrs_length %d\n",dmrs_length); - LOG_D(MAC,"N_PRB_DMRS = %d\n",N_PRB_DMRS); + LOG_I(MAC,"mcs = %i\n", gNB_mac->sched_ctrlCommon->mcs); + LOG_I(MAC,"startSymbolIndex = %i\n", startSymbolIndex); + LOG_I(MAC,"nrOfSymbols = %i\n", nrOfSymbols); + LOG_I(MAC,"rbSize = %i\n", gNB_mac->sched_ctrlCommon->rbSize); + LOG_I(MAC,"TBS = %i\n", TBS); + LOG_I(MAC,"dmrs_length %d\n",dmrs_length); + LOG_I(MAC,"N_PRB_DMRS = %d\n",N_PRB_DMRS); // Mark the corresponding RBs as used for (int rb = 0; rb < gNB_mac->sched_ctrlCommon->rbSize; rb++) { vrb_map[rb + rbStart] = 1; } + return TBS; } void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, @@ -547,8 +549,6 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) // TODO: Get these values from RRC const int CC_id = 0; int time_domain_allocation = 0; - uint8_t mcsTableIdx = 0; - uint8_t mcs = 6; uint8_t candidate_idx = 0; gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; @@ -588,27 +588,22 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) LOG_D(NR_MAC,"SIB1: \n"); for (int k=0;kcommon_channels->ServingCellConfigCommon->dmrs_TypeA_Position == 0) { - startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->time_domain_allocation][1]; - nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos2[gNB_mac->sched_ctrlCommon->time_domain_allocation][2]; - } else { - startSymbolIndex = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->time_domain_allocation][1]; - nrOfSymbols = table_5_1_2_1_1_2_time_dom_res_alloc_A_dmrs_typeA_pos3[gNB_mac->sched_ctrlCommon->time_domain_allocation][2]; - } - - // Calculate number of PRB_DMRS - uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6; - uint16_t dlDmrsSymbPos = fill_dmrs_mask(NULL, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, nrOfSymbols, startSymbolIndex); - uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos); - const uint32_t TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), - nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), - gNB_mac->sched_ctrlCommon->rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0 ,0 ,1 ) >> 3; - + + get_info_from_tda_tables(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern, + time_domain_allocation, + gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, + 1, &startSymbolIndex, &nrOfSymbols); + + // Configure sched_ctrlCommon for SIB1 + uint32_t TBS = schedule_control_sib1(module_idP, CC_id, + type0_PDCCH_CSS_config, + time_domain_allocation, + startSymbolIndex, + nrOfSymbols, + candidate_idx, sib1_sdu_length); + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; nr_fill_nfapi_dl_sib1_pdu(module_idP, dl_req, type0_PDCCH_CSS_config, TBS, startSymbolIndex, nrOfSymbols); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 9ea9806048..ee35768584 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -69,14 +69,14 @@ void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, sub_frame_t slot); -void schedule_control_sib1(module_id_t module_id, - int CC_id, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - uint8_t mcsTableIdx, - uint8_t mcs, - uint8_t candidate_idx, - int num_total_bytes); +uint32_t schedule_control_sib1(module_id_t module_id, + int CC_id, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + int time_domain_allocation, + int startSymbolIndex, + int nrOfSymbols, + uint8_t candidate_idx, + int num_total_bytes); void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); From d6c70f85d28cf9118124914025e0d5a6cf1c4f8a Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 3 May 2021 14:30:58 +0200 Subject: [PATCH 081/185] sib1 tda from config file --- openair2/COMMON/rrc_messages_types.h | 1 + openair2/F1AP/f1ap_du_rrc_message_transfer.c | 1 + openair2/GNB_APP/gnb_config.c | 2 ++ openair2/GNB_APP/gnb_paramdef.h | 7 +++++-- openair2/LAYER2/NR_MAC_gNB/config.c | 2 ++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 17 +++++++++-------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 + openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 ++ openair2/RRC/NR/nr_rrc_defs.h | 3 ++- openair2/RRC/NR/rrc_gNB.c | 4 ++++ openair2/RRC/NR/rrc_gNB_nsa.c | 2 ++ .../PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf | 2 ++ .../PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf | 2 ++ ...gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf | 3 ++- .../CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf | 1 + .../CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 1 + 16 files changed, 39 insertions(+), 12 deletions(-) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 64c42eaf0e..5086cd1b25 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -408,6 +408,7 @@ typedef struct NRRrcConfigurationReq_s { NR_ServingCellConfigCommon_t *scc; NR_ServingCellConfig_t *scd; int ssb_SubcarrierOffset; + int sib1_tda; int pdsch_AntennaPorts; int pusch_AntennaPorts; int pusch_TargetSNRx10; diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 23e6b29217..0aaa77e77f 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -1296,6 +1296,7 @@ int DU_handle_DL_NR_RRC_MESSAGE_TRANSFER(instance_t instance, rrc->carrier.ssb_SubcarrierOffset, rrc->carrier.pdsch_AntennaPorts, rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, NULL, 0, ue_context_p->ue_context.rnti, diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index d014aa9bd2..edfe175f92 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1009,6 +1009,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr; printf("pusch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr); NRRRC_CONFIGURATION_REQ (msg_p).pusch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr; + NRRRC_CONFIGURATION_REQ (msg_p).sib1_tda = *GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr; NRRRC_CONFIGURATION_REQ (msg_p).scc = scc; NRRRC_CONFIGURATION_REQ (msg_p).scd = scd; @@ -1881,6 +1882,7 @@ void configure_gnb_du_mac(int inst) { rrc->configuration.ssb_SubcarrierOffset, rrc->configuration.pdsch_AntennaPorts, rrc->configuration.pusch_AntennaPorts, + rrc->configuration.sib1_tda, rrc->configuration.scc, 0, 0, // rnti diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 6d9c9b8342..c7987853ad 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -116,6 +116,7 @@ typedef enum { #define GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET "ssb_SubcarrierOffset" #define GNB_CONFIG_STRING_PDSCHANTENNAPORTS "pdsch_AntennaPorts" #define GNB_CONFIG_STRING_PUSCHANTENNAPORTS "pusch_AntennaPorts" +#define GNB_CONFIG_STRING_SIB1TDA "sib1_tda" #define GNB_CONFIG_STRING_NRCELLID "nr_cellid" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ @@ -140,7 +141,8 @@ typedef enum { {GNB_CONFIG_STRING_SSBSUBCARRIEROFFSET, NULL, 0, iptr:NULL, defintval:31, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_PDSCHANTENNAPORTS, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \ {GNB_CONFIG_STRING_PUSCHANTENNAPORTS, NULL, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \ -{GNB_CONFIG_STRING_NRCELLID , NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \ +{GNB_CONFIG_STRING_SIB1TDA, NULL, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \ +{GNB_CONFIG_STRING_NRCELLID , NULL, 0, u64ptr:NULL, defint64val:1, TYPE_UINT64, 0}, \ } #define GNB_GNB_ID_IDX 0 @@ -160,7 +162,8 @@ typedef enum { #define GNB_SSB_SUBCARRIEROFFSET_IDX 14 #define GNB_PDSCH_ANTENNAPORTS_IDX 15 #define GNB_PUSCH_ANTENNAPORTS_IDX 16 -#define GNB_NRCELLID_IDX 17 +#define GNB_SIB1_TDA_IDX 17 +#define GNB_NRCELLID_IDX 18 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define GNBPARAMS_CHECK { \ diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 64c18d969c..310e980535 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -338,6 +338,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, int ssb_SubcarrierOffset, int pdsch_AntennaPorts, int pusch_AntennaPorts, + int sib1_tda, NR_ServingCellConfigCommon_t *scc, int add_ue, uint32_t rnti, @@ -408,6 +409,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, if (get_softmodem_params()->sa > 0) { NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[0]; + RC.nrmac[Mod_idP]->sib1_tda = sib1_tda; for (int n=0;nra[n].cfra = false; cc->ra[n].rnti = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 0a4f053817..2c567fa871 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -392,13 +392,13 @@ uint32_t schedule_control_sib1(module_id_t module_id, gNB_mac->sched_ctrlCommon->rbSize = rbSize; gNB_mac->sched_ctrlCommon->rbStart = 0; - LOG_I(MAC,"mcs = %i\n", gNB_mac->sched_ctrlCommon->mcs); - LOG_I(MAC,"startSymbolIndex = %i\n", startSymbolIndex); - LOG_I(MAC,"nrOfSymbols = %i\n", nrOfSymbols); - LOG_I(MAC,"rbSize = %i\n", gNB_mac->sched_ctrlCommon->rbSize); - LOG_I(MAC,"TBS = %i\n", TBS); - LOG_I(MAC,"dmrs_length %d\n",dmrs_length); - LOG_I(MAC,"N_PRB_DMRS = %d\n",N_PRB_DMRS); + LOG_D(MAC,"mcs = %i\n", gNB_mac->sched_ctrlCommon->mcs); + LOG_D(MAC,"startSymbolIndex = %i\n", startSymbolIndex); + LOG_D(MAC,"nrOfSymbols = %i\n", nrOfSymbols); + LOG_D(MAC,"rbSize = %i\n", gNB_mac->sched_ctrlCommon->rbSize); + LOG_D(MAC,"TBS = %i\n", TBS); + LOG_D(MAC,"dmrs_length %d\n",dmrs_length); + LOG_D(MAC,"N_PRB_DMRS = %d\n",N_PRB_DMRS); // Mark the corresponding RBs as used for (int rb = 0; rb < gNB_mac->sched_ctrlCommon->rbSize; rb++) { vrb_map[rb + rbStart] = 1; @@ -548,12 +548,13 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) // TODO: Get these values from RRC const int CC_id = 0; - int time_domain_allocation = 0; uint8_t candidate_idx = 0; gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; + int time_domain_allocation = gNB_mac->sib1_tda; + int L_max; switch (scc->ssb_PositionsInBurst->present) { case 1: diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index ee35768584..144cca09d1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -51,6 +51,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, int ssb_SubcarrierOffset, int pdsch_AntennaPorts, int pusch_AntennaPorts, + int sib1_tda, NR_ServingCellConfigCommon_t *scc, int nsa_flag, uint32_t rnti, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index ca11da372f..be96716570 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -616,6 +616,8 @@ typedef struct gNB_MAC_INST_s { int pucch_target_snrx10; /// Subcarrier Offset int ssb_SubcarrierOffset; + /// SIB1 Time domain allocation + int sib1_tda; /// Common cell resources NR_COMMON_channels_t common_channels[NFAPI_CC_MAX]; /// current PDU index (BCH,DLSCH) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 1483693ac6..3086277422 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -442,7 +442,8 @@ typedef struct { NR_SIB2_t *sib2; NR_SIB3_t *sib3; NR_BCCH_DL_SCH_Message_t systemInformation; // SIB23 - int ssb_SubcarrierOffset; + int ssb_SubcarrierOffset; + int sib1_tda; int pdsch_AntennaPorts; int pusch_AntennaPorts; int pusch_TargetSNRx10; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index f360e966b2..60402cfc92 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -239,6 +239,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration rrc->carrier.ssb_SubcarrierOffset, rrc->carrier.pdsch_AntennaPorts, rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, (NR_ServingCellConfigCommon_t *)rrc->carrier.servingcellconfigcommon, 0, 0, // WIP hardcoded rnti @@ -331,6 +332,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu rrc->carrier.ssb_SubcarrierOffset = configuration->ssb_SubcarrierOffset; rrc->carrier.pdsch_AntennaPorts = configuration->pdsch_AntennaPorts; rrc->carrier.pusch_AntennaPorts = configuration->pusch_AntennaPorts; + rrc->carrier.sib1_tda = configuration->sib1_tda; /// System Information INIT pthread_mutex_init(&rrc->cell_info_mutex,NULL); rrc->cell_info_configured = 0; @@ -493,6 +495,7 @@ rrc_gNB_generate_RRCSetup( rrc->carrier.ssb_SubcarrierOffset, rrc->carrier.pdsch_AntennaPorts, rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, NULL, 0, ue_context_pP->ue_context.rnti, @@ -564,6 +567,7 @@ rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest( rrc_instance_p->carrier.ssb_SubcarrierOffset, rrc_instance_p->carrier.pdsch_AntennaPorts, rrc_instance_p->carrier.pusch_AntennaPorts, + rrc_instance_p->carrier.sib1_tda, (NR_ServingCellConfigCommon_t *)rrc_instance_p->carrier.servingcellconfigcommon, 0, ue_context_pP->ue_context.rnti, diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 2e731f2185..fd5f42294a 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -349,6 +349,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ rrc->carrier.ssb_SubcarrierOffset, rrc->carrier.pdsch_AntennaPorts, rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, rrc->carrier.servingcellconfigcommon, 1, // add_ue flag ue_context_p->ue_id_rnti, @@ -358,6 +359,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ rrc->carrier.ssb_SubcarrierOffset, rrc->carrier.pdsch_AntennaPorts, rrc->carrier.pusch_AntennaPorts, + rrc->carrier.sib1_tda, NULL, 1, // add_ue flag ue_context_p->ue_id_rnti, diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf index 483fd34f2a..bfb268fef8 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf @@ -34,6 +34,8 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + sib1_tda = 0; servingCellConfigCommon = ( { diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf index dcb3010f20..7b3535ce1f 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf @@ -26,6 +26,8 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; + pusch_AntennaPorts = 1; + sib1_tda = 0; servingCellConfigCommon = ( { diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf index 753bd0bed3..1b0c15ea7a 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf @@ -38,7 +38,8 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; - + pusch_AntennaPorts = 1; + sib1_tda = 0; servingCellConfigCommon = ( { #spCellConfigCommon diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf index 20423b50b9..b64e9d1cbc 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf @@ -22,6 +22,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; pusch_AntennaPorts = 1; + sib1_tda = 0; pdcch_ConfigSIB1 = ( { diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index f91650cdc1..a3548b61df 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -37,6 +37,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; pusch_AntennaPorts = 1; + sib1_tda = 0; pdcch_ConfigSIB1 = ( { From e7425965ed76206d24672055c7979271b2bef054 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 3 May 2021 20:46:10 +0200 Subject: [PATCH 082/185] Fixing UE OFDM symbol generation The CP length was hard coded for numerology 1 --- openair1/PHY/MODULATION/modulation_common.h | 2 +- openair1/PHY/MODULATION/ofdm_mod.c | 68 +++++++++++++++++---- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 3 +- openair1/SCHED_NR/nr_ru_procedures.c | 2 + openair1/SIMULATION/NR_PHY/dlsim.c | 3 +- 5 files changed, 62 insertions(+), 16 deletions(-) diff --git a/openair1/PHY/MODULATION/modulation_common.h b/openair1/PHY/MODULATION/modulation_common.h index f550eeca5f..1a19bec78c 100644 --- a/openair1/PHY/MODULATION/modulation_common.h +++ b/openair1/PHY/MODULATION/modulation_common.h @@ -49,7 +49,7 @@ void PHY_ofdm_mod(int *input, void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRAME_PARMS *frame_parms); -void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms); +void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms, uint32_t slot); void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms); diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 8cf9f05b9b..2f075e8218 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -63,20 +63,62 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA } -void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms) +void nr_normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,NR_DL_FRAME_PARMS *frame_parms, uint32_t slot) { - PHY_ofdm_mod(txdataF, // input - txdata, // output - frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples0, // number of prefix samples - CYCLIC_PREFIX); - PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size, // input - txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, // output - frame_parms->ofdm_symbol_size, - nsymb - 1, - frame_parms->nb_prefix_samples, // number of prefix samples - CYCLIC_PREFIX); + // This function works only slot wise. For more generic symbol generation refer nr_feptx0() + if (frame_parms->numerology_index != 0) { // case where numerology != 0 + if (!(slot%(frame_parms->slots_per_subframe/2))) { + PHY_ofdm_mod(txdataF, + txdata, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size, + txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, + frame_parms->ofdm_symbol_size, + nsymb - 1, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } + else { + PHY_ofdm_mod(txdataF, + txdata, + frame_parms->ofdm_symbol_size, + nsymb, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } + } + else { // numerology = 0, longer CP for every 7th symbol + PHY_ofdm_mod(txdataF, + txdata, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size, + txdata + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, + frame_parms->ofdm_symbol_size, + 6, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + PHY_ofdm_mod(txdataF + 7*frame_parms->ofdm_symbol_size, + txdata + 6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples) + + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0, + frame_parms->ofdm_symbol_size, + 1, + frame_parms->nb_prefix_samples0, + CYCLIC_PREFIX); + PHY_ofdm_mod(txdataF + 8*frame_parms->ofdm_symbol_size, + txdata + 6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples) + + 2*(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples0), + frame_parms->ofdm_symbol_size, + 6, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } + } void PHY_ofdm_mod(int *input, /// pointer to complex input diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 1536dc9d90..4242b6b9d9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -525,7 +525,8 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, nr_normal_prefix_mod(txdataF[ap], &txdata[ap][tx_offset], 14, - frame_parms); + frame_parms, + slot); } } diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 1b2baf03f5..867519adea 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -122,6 +122,7 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { fp->nb_prefix_samples, CYCLIC_PREFIX); slot_offset += fp->nb_prefix_samples+fp->ofdm_symbol_size; + slot_offsetF += fp->ofdm_symbol_size; } else { PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF], @@ -131,6 +132,7 @@ void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) { fp->nb_prefix_samples0, CYCLIC_PREFIX); slot_offset += fp->nb_prefix_samples0+fp->ofdm_symbol_size; + slot_offsetF += fp->ofdm_symbol_size; } } } diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index d3cd33a918..bd5588f9f4 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1046,7 +1046,8 @@ int main(int argc, char **argv) nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset], &txdata[aa][tx_offset], 14, - frame_parms); + frame_parms, + slot); } } From 2437d58b17103ebed68a6db16307177f31083dff Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 4 May 2021 01:44:55 +0200 Subject: [PATCH 083/185] Fixing sample offset for PRACH rx --- openair1/PHY/NR_TRANSPORT/nr_prach.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 34c647810d..6d82209148 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -174,7 +174,11 @@ void rx_nr_prach_ru(RU_t *ru, int msg1_frequencystart = ru->config.prach_config.num_prach_fd_occasions_list[numRA].k1.value; - int sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1)); + int sample_offset_slot; + if (!(slot%(fp->slots_per_subframe/2))) + sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1)); + else + sample_offset_slot = (prachStartSymbol==0?0:prachStartSymbol*(fp->ofdm_symbol_size+fp->nb_prefix_samples)); //to be checked for mu=0; LOG_D(PHY,"frame %d, slot %d: doing rx_nr_prach_ru for format %d, numRA %d, prachStartSymbol %d, prachOccasion %d\n",frame,slot,prachFormat,numRA,prachStartSymbol,prachOccasion); From 014280bf135d064e3d7aa607cafb1b1db7087899 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 4 May 2021 16:47:30 +0200 Subject: [PATCH 084/185] NR_UE: fix PRACH TX timing for FR2 --- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 2c4c0b9e14..300366aefc 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -102,7 +102,11 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index, ue->X_u); - sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1)); + if (slot % (fp->slots_per_subframe / 2) == 0) + sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1)); + else + sample_offset_slot = (fp->ofdm_symbol_size + fp->nb_prefix_samples) * prachStartSymbol; + prach_start = fp->get_samples_slot_timestamp(slot, fp, 0) + sample_offset_slot; //printf("prachstartsymbold %d, sample_offset_slot %d, prach_start %d\n",prachStartSymbol, sample_offset_slot, prach_start); From 79489496042816268c2e8623a0865b8c15030977 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 10 May 2021 00:09:18 +0200 Subject: [PATCH 085/185] Smoothing the frequency response --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 285 +++++++++++++++++- openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c | 21 ++ openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h | 15 +- .../nr_dl_channel_estimation.c | 280 ++++++++++++++++- 4 files changed, 572 insertions(+), 29 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index fe945bfba6..682570bf67 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -518,9 +518,72 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + // First PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; - for (pilot_cnt=0; pilot_cnt<6*nb_rb_pusch; pilot_cnt += 6) { - int32_t ch_0, ch_1; + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + ul_ch, + 8); + ul_ch -= 24; + + for (pilot_cnt=6; pilot_cnt<6*(nb_rb_pusch-1); pilot_cnt += 6) { ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; @@ -566,51 +629,243 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; - ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; - ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; - ul_ch += 24; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + ul_ch, + 8); + ul_ch -= 16; } + // Last PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + ul_ch, + 8); } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + //First PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + ul_ch, + 8); + ul_ch -= 24; + for (pilot_cnt=0; pilot_cnt<4*nb_rb_pusch; pilot_cnt += 4) { - int32_t ch_0, ch_1; ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] = ch_0 / 4; ch[1] = ch_1 / 4; - ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; - ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; - ul_ch += 24; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + ul_ch, + 8); + ul_ch -= 16; } + // Last PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + ul_ch, + 8); } #ifdef DEBUG_PUSCH ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c index 990f3101fd..65ae288252 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c +++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c @@ -239,3 +239,24 @@ short filt8_dcll2[8] = { short filt8_dclh2[8] = { 0,0,0,0,1489,2979,4468,5958}; + +short filt8_avlip0[8] = { +16384,16384,16384,16384,16384,16384,16384,15019}; + +short filt8_avlip1[8] = { +13653,12288,10923,9557,8192,6827,5461,4096}; + +short filt8_avlip2[8] = { +2731,1365,0,0,0,0,0,0}; + +short filt8_avlip3[8] = { +2731,4096,5461,6827,8192,9557,10923,12288}; + +short filt8_avlip4[8] = { +13653,15019,16384,15019,13653,12288,10923,9557}; + +short filt8_avlip5[8] = { +8192,6827,5461,4096,2731,1365,0,0}; + +short filt8_avlip6[8] = { +13653,15019,16384,16384,16384,16384,16384,16384}; diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h index ef6137a07f..e28736b51d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h +++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h @@ -169,4 +169,17 @@ extern short filt8_dcll2[8]; extern short filt8_dclh2[8]; -#endif \ No newline at end of file +extern short filt8_avlip0[8]; + +extern short filt8_avlip1[8]; + +extern short filt8_avlip2[8]; + +extern short filt8_avlip3[8]; + +extern short filt8_avlip4[8]; + +extern short filt8_avlip5[8]; + +extern short filt8_avlip6[8]; +#endif 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 ab9a42c60d..56eafba87e 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1198,9 +1198,72 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, } } else if (config_type == pdsch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + dl_ch, + 8); + dl_ch -= 24; + for (pilot_cnt=0; pilot_cnt<6*nb_rb_pdsch; pilot_cnt += 6) { - int32_t ch_0, ch_1; ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; @@ -1246,13 +1309,140 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; - ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; - ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; - dl_ch += 24; + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + dl_ch, + 8); + dl_ch -= 16; } + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + dl_ch, + 8); } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + dl_ch, + 8); + dl_ch -= 24; + for (pilot_cnt=0; pilot_cnt<4*nb_rb_pdsch; pilot_cnt += 4) { int32_t ch_0, ch_1; @@ -1260,37 +1450,101 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] = ch_0 / 4; ch[1] = ch_1 / 4; - ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; - ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; - dl_ch += 24; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + dl_ch, + 8); + dl_ch -= 16; } + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + dl_ch, + 8); } #ifdef DEBUG_PDSCH dl_ch = (int16_t *)&dl_ch_estimates[p*ue->frame_parms.nb_antennas_rx+aarx][ch_offset]; From d621ad67e5b5f38edb0676eb8158c6a8f42fedac Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 10 May 2021 00:23:37 +0200 Subject: [PATCH 086/185] Fixied nrulsim --- openair1/SIMULATION/NR_PHY/ulsim.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 1061171f95..ead38f10a3 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1130,6 +1130,10 @@ int main(int argc, char **argv) phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id); + LOG_D(PHY, "Sending Uplink data \n"); + nr_ue_pusch_common_procedures(UE, + slot, + frame_parms,1); if (n_trials==1) { LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1); From 3ac2343ad951b8edb82340bc9ed3d37e7619c6ac Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 10 May 2021 11:15:51 +0200 Subject: [PATCH 087/185] Fixed start & end PRB --- openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 2 +- openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 682570bf67..1ba55f3df3 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -765,7 +765,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, 8); ul_ch -= 24; - for (pilot_cnt=0; pilot_cnt<4*nb_rb_pusch; pilot_cnt += 4) { + for (pilot_cnt=4; pilot_cnt<4*(nb_rb_pusch-1); pilot_cnt += 4) { ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; 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 56eafba87e..fea6c4d45c 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1263,7 +1263,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, 8); dl_ch -= 24; - for (pilot_cnt=0; pilot_cnt<6*nb_rb_pdsch; pilot_cnt += 6) { + for (pilot_cnt=6; pilot_cnt<6*(nb_rb_pdsch-1); pilot_cnt += 6) { ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; @@ -1443,7 +1443,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, 8); dl_ch -= 24; - for (pilot_cnt=0; pilot_cnt<4*nb_rb_pdsch; pilot_cnt += 4) { + for (pilot_cnt=4; pilot_cnt<4*(nb_rb_pdsch-1); pilot_cnt += 4) { int32_t ch_0, ch_1; ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; From 7d59106c5f1b6183840e3bbcf84441da8979f631 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 11 May 2021 02:26:59 +0530 Subject: [PATCH 088/185] nfapi working with latest threading architecture --- ci-scripts/Jenkinsfile-GitLab-Container | 261 +++++ ci-scripts/Jenkinsfile-gitlab | 33 +- ci-scripts/Jenkinsfile-tmp-multi-enb-benetel | 293 ++++++ ci-scripts/Jenkinsfile-tmp-multi-enb-nsa | 297 ++++++ ci-scripts/Jenkinsfile-tmp-ran | 44 +- ci-scripts/Jenkinsfile-trig-nsa | 73 ++ ci-scripts/buildOnVM.sh | 19 +- ci-scripts/cls_containerize.py | 125 +-- ci-scripts/conf_files/benetel-4g.conf | 285 ++++++ ci-scripts/conf_files/benetel-5g.conf | 317 ++++++ .../gnb.band66.tm1.106PRB.usrpn300.conf | 292 ++++++ .../gnb.band78.tm1.106PRB.usrpn300.conf | 20 +- ci-scripts/createVM.sh | 6 + ci-scripts/docker_log_split.py | 92 ++ ci-scripts/oai-ci-vm-tool | 9 +- ci-scripts/ran.py | 3 +- ci-scripts/reportBuildLocally.sh | 100 +- ci-scripts/reportTestLocally.sh | 2 +- ci-scripts/runTestOnVM.sh | 90 +- ci-scripts/waitBuildOnVM.sh | 12 + ..._test.xml => benetel_multi_node_build.xml} | 59 +- ci-scripts/xml_files/benetel_nsa_base.xml | 162 +++ ...ge_build.xml => container_image_build.xml} | 4 +- ci-scripts/xml_files/fr1_multi_node_build.xml | 2 + ...{fr1_ran_ue_iperf.xml => fr1_nsa_base.xml} | 39 +- ...1_ran_ue_base.xml => fr1_nsa_base_ref.xml} | 47 +- cmake_targets/CMakeLists.txt | 8 +- cmake_targets/autotests/test_case_list.xml | 8 +- cmake_targets/build_oai | 40 +- cmake_targets/tools/build_helper | 28 +- common/utils/LOG/log.c | 11 +- common/utils/LOG/log.h | 10 +- common/utils/T/.gitignore | 1 + common/utils/T/T_messages.txt | 8 +- common/utils/T/tracer/Makefile | 10 +- common/utils/T/tracer/gnb.c | 172 ++++ common/utils/T/tracer/logger/iqlog.c | 78 ++ common/utils/T/tracer/logger/logger.h | 2 + common/utils/nr/nr_common.c | 75 ++ common/utils/nr/nr_common.h | 14 + doc/NFAPI_archi.md | 132 +++ doc/RUNMODEM.md | 17 +- docker/Dockerfile.eNB.rhel8.2 | 5 +- docker/Dockerfile.eNB.ubuntu18 | 5 +- docker/Dockerfile.gNB.rhel8.2 | 5 +- docker/Dockerfile.gNB.ubuntu18 | 5 +- docker/Dockerfile.lteUE.rhel8.2 | 6 +- docker/Dockerfile.lteUE.ubuntu18 | 5 +- docker/Dockerfile.nrUE.rhel8.2 | 5 +- docker/Dockerfile.nrUE.ubuntu18 | 5 +- executables/nr-gnb.c | 730 ++----------- executables/nr-ru.c | 964 +++++------------- executables/nr-softmodem.c | 90 -- executables/nr-ue.c | 62 +- executables/nr-uesoftmodem.c | 97 +- executables/softmodem-common.h | 7 + nfapi/oai_integration/nfapi_pnf.c | 33 - .../nfapi/public_inc/nfapi_nr_interface_scf.h | 7 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 842 +++------------ nfapi/open-nFAPI/pnf/src/pnf_p7.c | 2 +- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 72 +- nfapi/open-nFAPI/vnf/inc/vnf_p7.h | 2 - nfapi/open-nFAPI/vnf/src/vnf_p7.c | 136 +-- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 48 +- openair1/PHY/INIT/nr_init.c | 59 +- openair1/PHY/INIT/nr_init_ue.c | 34 +- openair1/PHY/INIT/nr_parms.c | 119 +-- openair1/PHY/MODULATION/modulation_UE.h | 7 +- openair1/PHY/MODULATION/nr_modulation.c | 74 +- openair1/PHY/MODULATION/nr_modulation.h | 6 +- openair1/PHY/MODULATION/ofdm_mod.c | 22 +- openair1/PHY/MODULATION/slot_fep_nr.c | 619 +++++------ .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 12 +- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 90 +- openair1/PHY/NR_REFSIG/nr_dmrs_rx.c | 4 +- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 9 +- openair1/PHY/NR_TRANSPORT/nr_prach.c | 477 +++++---- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 1 + openair1/PHY/NR_TRANSPORT/pucch_rx.c | 9 +- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 9 +- .../nr_dlsch_llr_computation.c | 52 +- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 3 +- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 375 +++++-- .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 2 + .../PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c | 16 +- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 7 +- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 20 +- openair1/PHY/TOOLS/nr_phy_scope.c | 24 - openair1/PHY/defs_RU.h | 6 + openair1/PHY/defs_gNB.h | 12 + openair1/PHY/defs_nr_common.h | 19 +- openair1/SCHED_NR/fapi_nr_l1.c | 3 +- openair1/SCHED_NR/nr_ru_procedures.c | 6 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 27 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 185 ++-- openair1/SIMULATION/NR_PHY/dlsim.c | 57 +- openair1/SIMULATION/NR_PHY/nr_unitary_defs.h | 14 +- openair1/SIMULATION/NR_PHY/pbchsim.c | 16 +- openair1/SIMULATION/NR_PHY/prachsim.c | 24 +- openair1/SIMULATION/NR_PHY/ulsim.c | 127 ++- openair2/COMMON/rrc_messages_types.h | 2 + openair2/COMMON/s1ap_messages_types.h | 5 + openair2/ENB_APP/enb_config.c | 59 ++ openair2/ENB_APP/enb_paramdef.h | 15 + openair2/GNB_APP/RRC_nr_paramsvalues.h | 38 + openair2/GNB_APP/gnb_config.c | 190 ++++ openair2/LAYER2/MAC/mac.h | 2 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 284 +++--- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 14 +- openair2/LAYER2/NR_MAC_UE/config_ue.c | 7 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 + openair2/LAYER2/NR_MAC_UE/mac_proto.h | 4 +- openair2/LAYER2/NR_MAC_UE/mac_vars.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 66 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 28 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 117 ++- openair2/LAYER2/NR_MAC_gNB/config.c | 5 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 12 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 17 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 15 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 5 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 777 ++++++++++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 40 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 +- openair2/LAYER2/NR_MAC_gNB/main.c | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 113 +- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 262 ++++- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h | 57 +- .../LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c | 90 -- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 31 +- openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c | 78 ++ ...{nr_pdcp_entity_drb_am.h => nr_pdcp_sdu.h} | 30 +- .../LAYER2/nr_pdcp/nr_pdcp_timer_thread.c | 87 ++ .../LAYER2/nr_pdcp/nr_pdcp_timer_thread.h | 32 + openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c | 14 + openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h | 3 + openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 68 +- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 4 +- openair2/RRC/LTE/rrc_eNB_S1AP.c | 32 +- openair2/RRC/NR/nr_rrc_proto.h | 20 +- openair2/RRC/NR/nr_rrc_types.h | 6 +- openair2/RRC/NR/rrc_gNB.c | 4 +- openair2/RRC/NR/rrc_gNB_nsa.c | 14 +- openair2/RRC/NR/rrc_gNB_reconfig.c | 203 ++-- openair2/RRC/NR_UE/L2_interface_ue.c | 32 +- openair2/RRC/NR_UE/rrc_UE.c | 410 +++----- openair2/RRC/NR_UE/rrc_defs.h | 31 +- openair2/RRC/NR_UE/rrc_proto.h | 21 +- openair2/SIMULATION/NR_RRC/itti_sim.c | 2 +- openair2/X2AP/x2ap_eNB_generate_messages.c | 3 + openair2/X2AP/x2ap_eNB_handler.c | 35 +- openair3/GTPV1-U/gtpv1u_eNB.c | 2 +- openair3/NAS/COMMON/EMM/MSG/AttachAccept.c | 1 - openair3/NAS/COMMON/IES/SupportedCodecList.c | 4 + openair3/NAS/UE/EMM/SAP/emm_as.c | 4 +- openair3/NAS/UE/EMM/SecurityModeControl.c | 14 +- openair3/S1AP/s1ap_common.h | 7 +- openair3/S1AP/s1ap_eNB.c | 417 ++++++-- openair3/S1AP/s1ap_eNB.h | 17 + openair3/S1AP/s1ap_eNB_decoder.c | 2 - openair3/S1AP/s1ap_eNB_defs.h | 14 + openair3/S1AP/s1ap_eNB_handlers.c | 369 +++++-- .../S1AP/s1ap_eNB_management_procedures.c | 34 +- openair3/S1AP/s1ap_eNB_nas_procedures.c | 22 +- openair3/S1AP/s1ap_eNB_nnsf.c | 86 +- openair3/S1AP/s1ap_eNB_overload.c | 16 +- openair3/S1AP/s1ap_eNB_trace.c | 4 + openair3/SCTP/sctp_default_values.h | 4 +- openair3/SCTP/sctp_eNB_task.c | 12 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 4 +- targets/ARCH/rfsimulator/stored_node.c | 5 +- .../CONF/gnb.band66.tm1.106PRB.usrpn300.conf | 18 +- .../CONF/gnb.band66.tm1.106PRB.usrpx300.conf | 18 +- .../gnb.band78.tm1.106PRB.PTRS.usrpx300.conf | 331 ++++++ .../CONF/gnb.band78.tm1.106PRB.usrpn300.conf | 8 +- .../CONF/gnb.band78.tm1.106PRB.usrpx300.conf | 27 +- .../CONF/gnb.band78.tm1.24PRB.usrpb210.conf | 292 ++++++ .../CONF/gnb.band78.tm1.24PRB.usrpn300.conf | 290 ++++++ .../CONF/gnb.band78.tm1.24PRB.usrpx300.conf | 290 ++++++ .../CONF/testing_gnb_24PRB.conf | 306 ++++++ .../gnb.sa.band78.fr1.106PRB.usrpb210.conf | 11 +- 182 files changed, 9786 insertions(+), 5217 deletions(-) create mode 100644 ci-scripts/Jenkinsfile-GitLab-Container create mode 100644 ci-scripts/Jenkinsfile-tmp-multi-enb-benetel create mode 100644 ci-scripts/Jenkinsfile-tmp-multi-enb-nsa create mode 100644 ci-scripts/Jenkinsfile-trig-nsa create mode 100644 ci-scripts/conf_files/benetel-4g.conf create mode 100644 ci-scripts/conf_files/benetel-5g.conf create mode 100644 ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf create mode 100644 ci-scripts/docker_log_split.py rename ci-scripts/xml_files/{fr1_multi_node_test.xml => benetel_multi_node_build.xml} (50%) create mode 100644 ci-scripts/xml_files/benetel_nsa_base.xml rename ci-scripts/xml_files/{fr1_image_build.xml => container_image_build.xml} (93%) rename ci-scripts/xml_files/{fr1_ran_ue_iperf.xml => fr1_nsa_base.xml} (80%) rename ci-scripts/xml_files/{fr1_ran_ue_base.xml => fr1_nsa_base_ref.xml} (80%) create mode 100644 common/utils/T/tracer/gnb.c create mode 100644 doc/NFAPI_archi.md delete mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c rename openair2/LAYER2/nr_pdcp/{nr_pdcp_entity_drb_am.h => nr_pdcp_sdu.h} (58%) create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container new file mode 100644 index 0000000000..fbf9ba8f4b --- /dev/null +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -0,0 +1,261 @@ +#!/bin/groovy +/* + * 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 + */ + +// Location of the executor node +def nodeExecutor = params.nodeExecutor + +// Tags to shorten pipeline duration +def doMandatoryTests = false +def doFullTestsuite = false + +pipeline { + agent { + label nodeExecutor + } + options { + disableConcurrentBuilds() + timestamps() + gitLabConnection('OAI GitLab') + ansiColor('xterm') + } + + stages { + stage ("Verify Parameters") { + steps { + script { + JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"' + JOB_TIMESTAMP = JOB_TIMESTAMP.trim() + + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + echo '\u2705 \u001B[32mVerify Labels\u001B[0m' + if ("MERGE".equals(env.gitlabActionType)) { + LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid + LABEL_CHECK = LABEL_CHECK.trim() + if (LABEL_CHECK == 'NONE') { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request has none of the mandatory labels:\n\n" + message += " - BUILD-ONLY\n" + message += " - 4G-LTE\n" + message += " - 5G-NR\n" + message += " - CI\n\n" + message += "Not performing CI due to lack of labels" + addGitLabMRComment comment: message + error('Not performing CI due to lack of labels') + } else if (LABEL_CHECK == 'FULL') { + doMandatoryTests = true + doFullTestsuite = true + } else if (LABEL_CHECK == 'SHORTEN-5G') { + doMandatoryTests = true + } else { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): We will perform only build stages on your Merge Request" + addGitLabMRComment comment: message + } + } else { + doMandatoryTests = true + doFullTestsuite = true + } + } + } + } + stage ("Verify Guidelines") { + steps { + echo "Git URL is ${GIT_URL}" + echo "GitLab Act is ${env.gitlabActionType}" + script { + if ("MERGE".equals(env.gitlabActionType)) { + // since a bit, in push events, gitlabUserEmail is not populated + gitCommitAuthorEmailAddr = env.gitlabUserEmail + echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}" + // GitLab-Jenkins plugin integration is lacking to perform the merge by itself + // Doing it manually --> it may have merge conflicts + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}" + } else { + echo "Git Branch is ${GIT_BRANCH}" + echo "Git Commit is ${GIT_COMMIT}" + // since a bit, in push events, gitlabUserEmail is not populated + gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}' + gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim() + echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}" + sh "git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG" + } + } + } + post { + failure { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI" + addGitLabMRComment comment: message + currentBuild.result = 'FAILURE' + } + } + } + } + // Build Stages are Mandatory + // Later we will add a Ubuntu20 build + stage ("Image Building Processes") { + parallel { + stage ("Ubuntu18 Build") { + steps { + script { + triggerSlaveJob ('RAN-Ubuntu18-Image-Builder', 'Ubuntu18-Images-Build') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-Ubuntu18-Image-Builder') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + stage ("RHEL8 Build") { + steps { + script { + triggerSlaveJob ('RAN-RHEL8-Image-Builder', 'RHEL8-Images-Build') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-RHEL8-Image-Builder') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + } + } + } + post { + always { + script { + emailext attachmentsPattern: '*results*.html', + body: '''Hi, + +Here are attached HTML report files for $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS! + +Regards, +OAI CI Team''', + replyTo: 'no-reply@openairinterface.org', + subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', + to: gitCommitAuthorEmailAddr + + if (fileExists('.git/CI_COMMIT_MSG')) { + sh "rm -f .git/CI_COMMIT_MSG" + } + } + } + success { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + } + } + } + failure { + script { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")" + if ("MERGE".equals(env.gitlabActionType)) { + echo "This is a MERGE event" + addGitLabMRComment comment: message + } + } + } + } +} + +// ---- Slave Job functions + +def triggerSlaveJob (jobName, gitlabStatusName) { + // Workaround for the "cancelled" GitLab pipeline notification + // The slave job is triggered with the propagate false so the following commands are executed + // Its status is now PASS/SUCCESS from a stage pipeline point of view + // localStatus variable MUST be analyzed to properly assess the status + localStatus = build job: jobName, + parameters: [ + string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)), + string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)), + string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)), + booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)), + string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch)) + ], propagate: false + localResult = localStatus.getResult() + echo "${jobName} Slave Job status is ${localResult}" + gitlabCommitStatus(name: gitlabStatusName) { + if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) { + echo "${jobName} Slave Job is OK" + } else { + echo "${jobName} Slave Job is KO" + sh "ci-scripts/fail.sh" + } + } +} + +def triggerSlaveJobNoGitLab (jobName) { + // Workaround for the "cancelled" GitLab pipeline notification + // The slave job is triggered with the propagate false so the following commands are executed + // Its status is now PASS/SUCCESS from a stage pipeline point of view + // localStatus variable MUST be analyzed to properly assess the status + localStatus = build job: jobName, + parameters: [ + string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)), + string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)), + string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)), + booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)), + string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch)) + ], propagate: false + localResult = localStatus.getResult() + echo "${jobName} Slave Job status is ${localResult}" + if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) { + echo "${jobName} Slave Job is OK" + } else { + echo "${jobName} Slave Job is KO" + sh "ci-scripts/fail.sh" + } +} + +def finalizeSlaveJob(jobName) { + // In case of any non-success, we are retrieving the HTML report of the last completed + // slave job. The only drop-back is that we may retrieve the HTML report of a previous build + fileName = "test_results-${jobName}.html" + if (!fileExists(fileName)) { + copyArtifacts(projectName: jobName, + filter: 'test_results*.html', + selector: lastCompleted()) + if (fileExists(fileName)) { + sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' ${fileName}" + archiveArtifacts artifacts: fileName + } + } +} diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index ff661543c0..de49275b7e 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -196,16 +196,6 @@ pipeline { } } - stage ("Start VM -- enb-usrp") { - steps { - lock (vmResource) { - timeout (time: 5, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool build --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --daemon" - } - } - } - } - stage ("Start VM -- phy-sim") { steps { lock (vmResource) { @@ -251,7 +241,7 @@ pipeline { stage ("Analysis with cppcheck") { steps { gitlabCommitStatus(name: "Analysis with cppcheck") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant cppcheck --job-name ${JOB_NAME} --build-id ${BUILD_ID}" } } @@ -260,7 +250,7 @@ pipeline { stage ("Build basic simulator") { steps { gitlabCommitStatus(name: "Build basic-sim") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant basic-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -269,7 +259,7 @@ pipeline { stage ("Build 5G gNB-USRP") { steps { gitlabCommitStatus(name: "Build gNB-USRP") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant gnb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -278,25 +268,16 @@ pipeline { stage ("Build 5G NR-UE-USRP") { steps { gitlabCommitStatus(name: "Build nr-UE-USRP") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant nr-ue-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } } } - stage ("Build eNB-USRP") { - steps { - gitlabCommitStatus(name: "Build eNB-USRP") { - timeout (time: 20, unit: 'MINUTES') { - sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-usrp --job-name ${JOB_NAME} --build-id ${BUILD_ID}" - } - } - } - } stage ("Build physical simulators") { steps { gitlabCommitStatus(name: "Build phy-sim") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant phy-sim --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -305,7 +286,7 @@ pipeline { stage ("Build eNB-ethernet") { steps { gitlabCommitStatus(name: "Build eNB-ethernet") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant enb-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } @@ -316,7 +297,7 @@ pipeline { // This is typically the last one to finish. lock (vmResource) { gitlabCommitStatus(name: "Build UE-ethernet") { - timeout (time: 20, unit: 'MINUTES') { + timeout (time: 30, unit: 'MINUTES') { sh "./ci-scripts/oai-ci-vm-tool wait --workspace $WORKSPACE --variant ue-ethernet --job-name ${JOB_NAME} --build-id ${BUILD_ID} --keep-vm-alive" } } diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel new file mode 100644 index 0000000000..8ac2e6adff --- /dev/null +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-benetel @@ -0,0 +1,293 @@ +#!/bin/groovy +/* + * 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 + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the phone resource +def ciSmartPhonesResource1 = params.SmartPhonesResource1 +def ciSmartPhonesResource2 = params.SmartPhonesResource2 + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess +def eNB_TargetBranch + +pipeline { + agent { + label pythonExecutor + } + options { + disableConcurrentBuilds() + ansiColor('xterm') + lock(extra: [[resource: ciSmartPhonesResource2]], resource: ciSmartPhonesResource1) + } + stages { + stage("Build Init") { + steps { + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${params.eNB_Branch}" + } + } + stage ("Verify Parameters") { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + + if (params.SmartPhonesResource1 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource2 == null) { + allParametersPresent = false + } + // 1st eNB parameters + if (params.eNB_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB_Credentials == null) { + allParametersPresent = false + } + // 2nd eNB parameters + if (params.eNB1_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB1_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB1_Credentials == null) { + allParametersPresent = false + } + // 3rd eNB parameters + if (params.eNB2_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB2_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB2_Credentials == null) { + allParametersPresent = false + } + // the following 4 parameters should be pushed by the master trigger + // if not present, take the job GIT variables (used for developing) + if (params.eNB_Repository == null) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_AllowMergeRequestProcess!= null) { + eNB_AllowMergeRequestProcess = params.eNB_AllowMergeRequestProcess + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + + if (params.ADB_IPAddress == null) { + allParametersPresent = false + } + if (params.ADB_Credentials == null) { + allParametersPresent = false + } + + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + stage ("Build and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + } + } + } + } + } + stage('Log Collection') { + parallel { + stage('Log Collection (eNB - Build)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("build.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "build.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (eNB - Run)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("enb.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "enb.log.${env.BUILD_ID}.zip" + } + if(fileExists("ci-scripts/test_results.html")) { + sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts "test_results-${JOB_NAME}.html" + } + } + } + } + } + } + } + + post { + always { + script { + if (params.pipelineZipsConsoleLog != null) { + if (params.pipelineZipsConsoleLog) { + echo "Archiving Jenkins console log" + sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true" + sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true" + if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa new file mode 100644 index 0000000000..66d12eed33 --- /dev/null +++ b/ci-scripts/Jenkinsfile-tmp-multi-enb-nsa @@ -0,0 +1,297 @@ +#!/bin/groovy +/* + * 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 + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +// Location of the test XML file to be run +def testXMLFile = params.pythonTestXmlFile +def mainPythonAllXmlFiles = "" +def buildStageStatus = true + +// Name of the test stage +def testStageName = params.pipelineTestStageName + +// Name of the phone resource +def ciSmartPhonesResource1 = params.SmartPhonesResource1 +def ciSmartPhonesResource2 = params.SmartPhonesResource2 +def ciSmartPhonesResource3 = params.SmartPhonesResource3 + +// Global Parameters. Normally they should be populated when the master job +// triggers the slave job with parameters +def eNB_Repository +def eNB_Branch +def eNB_CommitID +def eNB_AllowMergeRequestProcess +def eNB_TargetBranch + +pipeline { + agent { + label pythonExecutor + } + options { + disableConcurrentBuilds() + ansiColor('xterm') + lock(extra: [[resource: ciSmartPhonesResource2],[resource: ciSmartPhonesResource3]], resource: ciSmartPhonesResource1) + } + stages { + stage("Build Init") { + steps { + // update the build name and description + buildName "${params.eNB_MR}" + buildDescription "Branch : ${params.eNB_Branch}" + } + } + stage ("Verify Parameters") { + steps { + script { + echo '\u2705 \u001B[32mVerify Parameters\u001B[0m' + def allParametersPresent = true + + // It is already to late to check it + if (params.pythonExecutor != null) { + echo "eNB CI executor node : ${pythonExecutor}" + } + // If not present picking a default Stage Name + if (params.pipelineTestStageName == null) { + // picking default + testStageName = 'Template Test Stage' + } + + if (params.SmartPhonesResource1 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource2 == null) { + allParametersPresent = false + } + if (params.SmartPhonesResource3== null) { + allParametersPresent = false + } + // 1st eNB parameters + if (params.eNB_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB_Credentials == null) { + allParametersPresent = false + } + // 2nd eNB parameters + if (params.eNB1_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB1_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB1_Credentials == null) { + allParametersPresent = false + } + // 3rd eNB parameters + if (params.eNB2_IPAddress == null) { + allParametersPresent = false + } + if (params.eNB2_SourceCodePath == null) { + allParametersPresent = false + } + if (params.eNB2_Credentials == null) { + allParametersPresent = false + } + // the following 4 parameters should be pushed by the master trigger + // if not present, take the job GIT variables (used for developing) + if (params.eNB_Repository == null) { + eNB_Repository = env.GIT_URL + } else { + eNB_Repository = params.eNB_Repository + } + echo "eNB_Repository : ${eNB_Repository}" + if (params.eNB_Branch == null) { + eNB_Branch = env.GIT_BRANCH + } else { + eNB_Branch = params.eNB_Branch + } + echo "eNB_Branch : ${eNB_Branch}" + if (params.eNB_CommitID == null) { + eNB_CommitID = env.GIT_COMMIT + } else { + eNB_CommitID = params.eNB_CommitID + } + echo "eNB_CommitID : ${eNB_CommitID}" + if (params.eNB_AllowMergeRequestProcess!= null) { + eNB_AllowMergeRequestProcess = params.eNB_AllowMergeRequestProcess + if (eNB_AllowMergeRequestProcess) { + if (params.eNB_TargetBranch != null) { + eNB_TargetBranch = params.eNB_TargetBranch + } else { + eNB_TargetBranch = 'develop' + } + echo "eNB_TargetBranch : ${eNB_TargetBranch}" + } + } + + if (params.EPC_IPAddress == null) { + allParametersPresent = false + } + if (params.EPC_Type == null) { + allParametersPresent = false + } + if (params.EPC_SourceCodePath == null) { + allParametersPresent = false + } + if (params.EPC_Credentials == null) { + allParametersPresent = false + } + + if (params.ADB_IPAddress == null) { + allParametersPresent = false + } + if (params.ADB_Credentials == null) { + allParametersPresent = false + } + + if (allParametersPresent) { + echo "All parameters are present" + if (eNB_AllowMergeRequestProcess) { + sh "git fetch" + sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest" + } else { + sh "git fetch" + sh "git checkout -f ${eNB_CommitID}" + } + } else { + echo "Some parameters are missing" + sh "./ci-scripts/fail.sh" + } + } + } + } + stage ("Build and Test") { + steps { + script { + dir ('ci-scripts') { + echo "\u2705 \u001B[32m${testStageName}\u001B[0m" + // If not present picking a default XML file + if (params.pythonTestXmlFile == null) { + // picking default + testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml' + echo "Test XML file(default): ${testXMLFile}" + mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " " + } else { + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " " + echo "Test XML file : ${xmlFile}" + } + } + } + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'], + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] + ]) { + sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} ${mainPythonAllXmlFiles}" + String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") + for (xmlFile in myXmlTestSuite) { + if (fileExists(xmlFile)) { + try { + sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --ADBIPAddress=${params.ADB_IPAddress} --ADBUserName=${ADB_Username} --ADBPassword=${ADB_Password} --XMLTestFile=${xmlFile}" + } catch (Exception e) { + currentBuild.result = 'FAILURE' + buildStageStatus = false + } + } + } + sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" + } + } + } + } + } + stage('Log Collection') { + parallel { + stage('Log Collection (eNB - Build)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("build.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "build.log.${env.BUILD_ID}.zip" + } + } + } + } + stage('Log Collection (eNB - Run)') { + steps { + withCredentials([ + [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] + ]) { + echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + + echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' + sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" + } + script { + if(fileExists("enb.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "enb.log.${env.BUILD_ID}.zip" + } + if(fileExists("ci-scripts/test_results.html")) { + sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html" + sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: ${BUILD_ID}#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html" + archiveArtifacts "test_results-${JOB_NAME}.html" + } + } + } + } + } + } + } + + post { + always { + script { + if (params.pipelineZipsConsoleLog != null) { + if (params.pipelineZipsConsoleLog) { + echo "Archiving Jenkins console log" + sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true" + sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true" + if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) { + archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip" + } + } + } + } + } + } +} diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran index ab1573de7f..7d5307620f 100644 --- a/ci-scripts/Jenkinsfile-tmp-ran +++ b/ci-scripts/Jenkinsfile-tmp-ran @@ -241,6 +241,10 @@ pipeline { stage ("Terminate") { parallel { stage('Terminate UE') { + // Bypassing this stage if there are no abd server defined + when { + expression { params.ADB_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate UE\u001B[0m' withCredentials([ @@ -275,6 +279,10 @@ pipeline { } } stage('Terminate SPGW') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate SPGW\u001B[0m' withCredentials([ @@ -292,6 +300,10 @@ pipeline { } } stage('Terminate MME') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate MME\u001B[0m' withCredentials([ @@ -309,6 +321,10 @@ pipeline { } } stage('Terminate HSS') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { echo '\u2705 \u001B[32mTerminate HSS\u001B[0m' withCredentials([ @@ -371,6 +387,10 @@ pipeline { } } stage('Log Collection (SPGW)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -389,6 +409,10 @@ pipeline { } } stage('Log Collection (MME)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -407,6 +431,10 @@ pipeline { } } stage('Log Collection (HSS)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -425,6 +453,10 @@ pipeline { } } stage('Log Collection (Ping)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -443,6 +475,10 @@ pipeline { } } stage('Log Collection (Iperf)') { + // Bypassing this stage if EPC server is not defined + when { + expression { params.EPC_IPAddress != "none" } + } steps { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] @@ -482,7 +518,7 @@ pipeline { // Making sure that we really shutdown every thing before leaving failure { script { - if (!termStatusArray[termUE]) { + if ((!termStatusArray[termUE]) && (params.ADB_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.ADB_Credentials}", usernameVariable: 'ADB_Username', passwordVariable: 'ADB_Password'] ]) { @@ -496,21 +532,21 @@ pipeline { sh "python3 ci-scripts/main.py --mode=TerminateeNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password}" } } - if (!termStatusArray[termSPGW]) { + if ((!termStatusArray[termSPGW]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { sh "python3 ci-scripts/main.py --mode=TerminateSPGW --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCType=${params.EPC_Type} --EPCSourceCodePath=${params.EPC_SourceCodePath}" } } - if (!termStatusArray[termMME]) { + if ((!termStatusArray[termMME]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { sh "python3 ci-scripts/main.py --mode=TerminateMME --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCType=${params.EPC_Type} --EPCSourceCodePath=${params.EPC_SourceCodePath}" } } - if (!termStatusArray[termHSS]) { + if ((!termStatusArray[termHSS]) && (params.EPC_IPAddress != "none")) { withCredentials([ [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'] ]) { diff --git a/ci-scripts/Jenkinsfile-trig-nsa b/ci-scripts/Jenkinsfile-trig-nsa new file mode 100644 index 0000000000..3dd5ce3b50 --- /dev/null +++ b/ci-scripts/Jenkinsfile-trig-nsa @@ -0,0 +1,73 @@ +#!/bin/groovy +/* + * 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 + */ + +// Template Jenkins Declarative Pipeline script to run Test w/ RF HW + +// Location of the python executor node shall be in the same subnet as the others servers +def pythonExecutor = params.pythonExecutor + +def TARGET_BRANCH = "develop" +def ALLOW_MERGE = true + +pipeline { + agent { + label pythonExecutor + } + stages { + stage ("Launcher") { + steps { + script { + //retrieve MR that are opened nd with tag READY_TO_BE_MERGED + MR_LIST= sh returnStdout: true, script: 'curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests?state=opened&per_page=100&labels=READY_TO_BE_MERGED" | jq ".[].iid" || true ' + echo "List of selected MR:\n${MR_LIST}" + def MR_ARRAY = MR_LIST.split('\n') + //for every selected MR, retrieve the branch name and the latest commit + for (MR in MR_ARRAY) { + SRC_BRANCH=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".source_branch" || true """ + SRC_BRANCH=SRC_BRANCH.trim() + COMMIT_ID=sh returnStdout: true, script: """curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/${MR}" | jq ".sha" || true """ + COMMIT_ID=COMMIT_ID.trim() + echo "Testing NSA on : ${MR} ${SRC_BRANCH} ${COMMIT_ID}" + //calling NSA sub job + build job: "RAN-CI-NSA-B210", wait : false, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE)) + ] + //calling Benetel sub job + build job: "RAN-CI-BENETEL", wait : false, propagate : false, parameters: [ + string(name: 'eNB_MR', value: String.valueOf(MR)), + string(name: 'eNB_Branch', value: String.valueOf(SRC_BRANCH)), + string(name: 'eNB_CommitID', value: String.valueOf(COMMIT_ID)), + string(name: 'eNB_TargetBranch', value: String.valueOf(TARGET_BRANCH)), + booleanParam(name: 'eNB_AllowMergeRequestProcess', value: Boolean.valueOf(ALLOW_MERGE)) + ] + } + } + } + } + } +} + + diff --git a/ci-scripts/buildOnVM.sh b/ci-scripts/buildOnVM.sh index 861cab0782..2b1a5e0c71 100755 --- a/ci-scripts/buildOnVM.sh +++ b/ci-scripts/buildOnVM.sh @@ -62,6 +62,12 @@ function build_on_vm { echo "ARCHIVES_LOC = $ARCHIVES_LOC" echo "BUILD_OPTIONS = $BUILD_OPTIONS" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME` if [ $IS_VM_ALIVE -eq 0 ] @@ -158,6 +164,9 @@ function build_on_vm { echo "cd tmp" >> $VM_CMDS echo "echo \"unzip -qq -DD ../localZip.zip\"" >> $VM_CMDS echo "unzip -qq -DD ../localZip.zip" >> $VM_CMDS + # Trying to make some room on filesystem before building + echo "rm ../localZip.zip" >> $VM_CMDS + echo "export CI_ENV=True" >> $VM_CMDS if [[ "$VM_NAME" == *"-cppcheck"* ]] then echo "mkdir cmake_targets/log" >> $VM_CMDS @@ -208,7 +217,15 @@ function build_on_vm { echo "echo \"./build_oai -I $BUILD_OPTIONS \"" >> $VM_CMDS echo "./build_oai -I $BUILD_OPTIONS > log/install-build.txt 2>&1" >> $VM_CMDS else - echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + if [[ "$VM_NAME" == *"-enb-ethernet"* ]] + then + echo "echo \"sleep 170 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + elif [[ "$VM_NAME" == *"-ue-ethernet"* ]] + then + echo "echo \"sleep 60 && ./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + else + echo "echo \"./build_oai -I $BUILD_OPTIONS\" > ./my-vm-build.sh" >> $VM_CMDS + fi echo "chmod 775 ./my-vm-build.sh " >> $VM_CMDS echo "echo \"sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh\"" >> $VM_CMDS echo "sudo -E daemon --inherit --unsafe --name=build_daemon --chdir=/home/ubuntu/tmp/cmake_targets -o /home/ubuntu/tmp/cmake_targets/log/install-build.txt ./my-vm-build.sh" >> $VM_CMDS diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 0c07dfe91f..0debe42468 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -35,6 +35,7 @@ import sys # arg import re # reg import logging import os +import shutil import time from multiprocessing import Process, Lock, SimpleQueue from zipfile import ZipFile @@ -124,7 +125,7 @@ class Containerize(): self.cli = 'docker' self.dockerfileprefix = '.ubuntu18' elif self.host == 'Red Hat': - self.cli = 'podman' + self.cli = 'sudo podman' self.dockerfileprefix = '.rhel8.2' imageNames = [] @@ -173,6 +174,7 @@ class Containerize(): # if the branch is not develop, then it is a merge request and we need to do # the potential merge. Note that merge conflicts should already been checked earlier imageTag = 'develop' + sharedTag = 'develop' if (self.ranAllowMerge): imageTag = 'ci-temp' if self.ranTargetBranch == '': @@ -188,38 +190,23 @@ class Containerize(): mySSH.command('mkdir -p tmp/entitlement/', '\$', 5) mySSH.command('sudo cp /etc/rhsm/ca/redhat-uep.pem tmp/ca/', '\$', 5) mySSH.command('sudo cp /etc/pki/entitlement/*.pem tmp/entitlement/', '\$', 5) - - #mySSH.close() - #return 0 + sharedimage = 'ran-build' # Let's remove any previous run artifacts if still there - mySSH.command(self.cli + ' image prune --force', '\$', 5) - mySSH.command(self.cli + ' image rm ' + sharedimage + ':' + imageTag, '\$', 5) + mySSH.command(self.cli + ' image prune --force', '\$', 30) + if (not self.ranAllowMerge): + mySSH.command(self.cli + ' image rm ' + sharedimage + ':' + sharedTag, '\$', 30) for image,pattern in imageNames: - mySSH.command(self.cli + ' image rm ' + image + ':' + imageTag, '\$', 5) - # Build the shared image - mySSH.command(self.cli + ' build --target ' + sharedimage + ' --tag ' + sharedimage + ':' + imageTag + ' --file docker/Dockerfile.ran' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 1600) - # Build the target image(s) - previousImage = sharedimage + ':' + imageTag - danglingShaOnes=[] - for image,pattern in imageNames: - # the archived Dockerfiles have "ran-build:latest" as base image - # we need to update them with proper tag - mySSH.command('sed -i -e "s#' + sharedimage + ':latest#' + sharedimage + ':' + imageTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5) - mySSH.command(self.cli + ' build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200) - # Retrieving the dangling image(s) for the log collection - mySSH.command(self.cli + ' images --filter "dangling=true" --filter "since=' + previousImage + '" -q | sed -e "s#^#sha=#"', '\$', 5) - result = re.search('sha=(?P[a-zA-Z0-9\-\_]+)', mySSH.getBefore()) - if result is not None: - danglingShaOnes.append((image, result.group('imageShaOne'))) - previousImage = image + ':' + imageTag + mySSH.command(self.cli + ' image rm ' + image + ':' + imageTag, '\$', 30) - imageTag = 'ci-temp' - # First verify if images were properly created. + # Build the shared image only on Push Events (not on Merge Requests) + if (not self.ranAllowMerge): + mySSH.command(self.cli + ' build --target ' + sharedimage + ' --tag ' + sharedimage + ':' + sharedTag + ' --file docker/Dockerfile.ran' + self.dockerfileprefix + ' --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 1600) + # First verify if the shared image was properly created. status = True - mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + sharedimage + ':' + imageTag, '\$', 5) - if mySSH.getBefore().count('No such object') != 0: - logging.error('Could not build properly ran-build') + mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + sharedimage + ':' + sharedTag, '\$', 5) + if mySSH.getBefore().count('o such image') != 0: + logging.error('\u001B[1m Could not build properly ran-build\u001B[0m') status = False else: result = re.search('Size *= *(?P[0-9\-]+) *bytes', mySSH.getBefore()) @@ -240,11 +227,40 @@ class Containerize(): self.allImagesSize['ran-build'] = str(round(imageSize,1)) + ' Gbytes' else: logging.debug('ran-build size is unknown') + # If the shared image failed, no need to continue + if not status: + # Recover the name of the failed container? + mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5) + mySSH.command(self.cli + ' image prune --force', '\$', 30) + mySSH.close() + logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTabFooter(False) + sys.exit(1) + else: + # Recover build logs, for the moment only possible when build is successful + mySSH.command(self.cli + ' create --name test ' + sharedimage + ':' + sharedTag, '\$', 5) + mySSH.command('mkdir -p cmake_targets/log/ran-build', '\$', 5) + mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-build', '\$', 5) + mySSH.command(self.cli + ' rm -f test', '\$', 5) + + # Build the target image(s) for image,pattern in imageNames: + # the archived Dockerfiles have "ran-build:latest" as base image + # we need to update them with proper tag + mySSH.command('sed -i -e "s#' + sharedimage + ':latest#' + sharedimage + ':' + sharedTag + '#" docker/Dockerfile.' + pattern + self.dockerfileprefix, '\$', 5) + mySSH.command(self.cli + ' build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + self.dockerfileprefix + ' . > cmake_targets/log/' + image + '.log 2>&1', '\$', 1200) + # split the log + mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5) + mySSH.command('python3 ci-scripts/docker_log_split.py --logfilename=cmake_targets/log/' + image + '.log', '\$', 5) + # checking the status of the build mySSH.command(self.cli + ' image inspect --format=\'Size = {{.Size}} bytes\' ' + image + ':' + imageTag, '\$', 5) - if mySSH.getBefore().count('No such object') != 0: - logging.error('Could not build properly ' + image) + if mySSH.getBefore().count('o such image') != 0: + logging.error('\u001B[1m Could not build properly ' + image + '\u001B[0m') status = False + # Here we should check if the last container corresponds to a failed command and destroy it + mySSH.command(self.cli + ' ps --quiet --filter "status=exited" -n1 | xargs ' + self.cli + ' rm -f', '\$', 5) + self.allImagesSize[image] = 'N/A -- Build Failed' else: result = re.search('Size *= *(?P[0-9\-]+) *bytes', mySSH.getBefore()) if result is not None: @@ -264,39 +280,27 @@ class Containerize(): self.allImagesSize[image] = str(round(imageSize,1)) + ' Gbytes' else: logging.debug('ran-build size is unknown') - if not status: - mySSH.close() - logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') - HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) - #HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) + self.allImagesSize[image] = 'unknown' + # Now pruning dangling images in between target builds + mySSH.command(self.cli + ' image prune --force', '\$', 30) - # Recover build logs, for the moment only possible when build is successful - mySSH.command(self.cli + ' create --name test ' + sharedimage + ':' + imageTag, '\$', 5) - mySSH.command('mkdir -p cmake_targets/log/ran-build', '\$', 5) - mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-build', '\$', 5) - mySSH.command(self.cli + ' rm -f test', '\$', 5) - for image,shaone in danglingShaOnes: - mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5) - mySSH.command(self.cli + ' create --name test ' + shaone, '\$', 5) - mySSH.command(self.cli + ' cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/' + image, '\$', 5) - mySSH.command(self.cli + ' rm -f test', '\$', 5) - mySSH.command(self.cli + ' image prune --force', '\$', 5) - mySSH.command('cd cmake_targets', '\$', 5) + # Analyzing the logs + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) - #mySSH.close() - - mySSH.command('cd /tmp/CI-eNB/cmake_targets', '\$', 5) + + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + mySSH.command('rm -f build_log_' + self.testCase_id + '.zip || true', '\$', 5) if (os.path.isfile('./build_log_' + self.testCase_id + '.zip')): os.remove('./build_log_' + self.testCase_id + '.zip') + if (os.path.isdir('./build_log_' + self.testCase_id)): + shutil.rmtree('./build_log_' + self.testCase_id) mySSH.command('zip -r -qq build_log_' + self.testCase_id + '.zip build_log_' + self.testCase_id, '\$', 5) mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/build_log_' + self.testCase_id + '.zip', '.') - #mySSH.command('rm -f build_log_' + self.testCase_id + '.zip','\$', 5) + mySSH.command('rm -f build_log_' + self.testCase_id + '.zip','\$', 5) mySSH.close() ZipFile('build_log_' + self.testCase_id + '.zip').extractall('.') - + #Trying to identify the errors and warnings for each built images imageNames1 = imageNames shared = ('ran-build','ran') @@ -328,9 +332,16 @@ class Containerize(): files[fil] = errorandwarnings self.collectInfo[image] = files - logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') - HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK) - HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) + if status: + logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) + else: + logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlNextTabHeaderTestRow(self.collectInfo, self.allImagesSize) + HTML.CreateHtmlTabFooter(False) + sys.exit(1) def DeployObject(self, HTML, EPC): if self.eNB_serverId[self.eNB_instance] == '0': diff --git a/ci-scripts/conf_files/benetel-4g.conf b/ci-scripts/conf_files/benetel-4g.conf new file mode 100644 index 0000000000..9423ebe56e --- /dev/null +++ b/ci-scripts/conf_files/benetel-4g.conf @@ -0,0 +1,285 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF4p5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2655000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 90; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -10; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + //SSB central frequency of NR secondary cell group (for ENDC NSA) + nr_scg_ssb_freq = 640000; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "yes"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.1"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 150; + } +); + +RUs = ( + { + //local_if_name = "enp129s0f0"; + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 35 -n 2 -b 0000:81:00.3 --proc-type auto --file-prefix ggg -- -p 0x1"; + #sdr_addrs = "softmodem -l 8 -n 2 -- -p 0x2"; + #remote_address = "127.0.0.2"; + #local_address = "127.0.0.1"; + #local_portc = 50000; + #remote_portc = 50000; + #local_portd = 50001; + #remote_portd = 50001; + local_rf = "no" + tr_preference = "raw_if4p5" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + eNB_instances = [0]; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + #parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/benetel-5g.conf b/ci-scripts/conf_files/benetel-5g.conf new file mode 100644 index 0000000000..0dfe7854ee --- /dev/null +++ b/ci-scripts/conf_files/benetel-5g.conf @@ -0,0 +1,317 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + #pusch_TargetSNRx10 = 200; + #pucch_TargetSNRx10 = 200; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is is the central frequency of SSB + absoluteFrequencySSB = 640000; //641272 + dl_frequencyBand = 78; + # the carrier frequency is assumed to be in the middle of the carrier, i.e. dl_absoluteFrequencyPointA_kHz + dl_carrierBandwidth*12*SCS_kHz/2 + dl_absoluteFrequencyPointA = 638728; //640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 4; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 74; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; + #preambleReceivedTargetPower = -104; + #preambleReceivedTargetPower = -108; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 2; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 1; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + #msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + #p0_NominalWithGrant =-90; + p0_NominalWithGrant =-118; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + #p0_nominal = -90; + p0_nominal = -118; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + #ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = -35; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "127.0.0.1"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "127.0.0.2/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "no" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + //clock_src = "internal"; + clock_src = "external"; + + local_if_name = "dpdk"; + sdr_addrs = "softmodem -m 2048 -l 34 -n 3 -b 0000:81:00.2 --proc-type auto --file-prefix hhh -- -p 0x1"; + remote_address = "127.0.0.2"; + local_address = "127.0.0.1"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + tr_preference = "raw_if4p5" + + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + //parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_DISABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf new file mode 100644 index 0000000000..32de0aa4f5 --- /dev/null +++ b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf @@ -0,0 +1,292 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 2150 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 433096; + dl_frequencyBand = 66; + # this is 2150 MHz + dl_absoluteFrequencyPointA = 430000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 + initialDLBWPstartSymbolAndLength_3 = 57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 66; + ul_absoluteFrequencyPointA = 350000; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13475; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf index aeba400cad..decaa392d7 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf @@ -23,7 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; - + servingCellConfigCommon = ( { #spCellConfigCommon @@ -227,14 +227,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( @@ -248,8 +249,15 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; } diff --git a/ci-scripts/createVM.sh b/ci-scripts/createVM.sh index 237a1a5d5e..b67668f0bc 100755 --- a/ci-scripts/createVM.sh +++ b/ci-scripts/createVM.sh @@ -87,6 +87,12 @@ function create_vm { echo "VM_CPU = $VM_CPU" echo "VM_DISK = $VM_DISK GBytes" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + echo "############################################################" echo "Creating VM ($VM_NAME) on Ubuntu Cloud Image base" echo "############################################################" diff --git a/ci-scripts/docker_log_split.py b/ci-scripts/docker_log_split.py new file mode 100644 index 0000000000..8c3c9e41dc --- /dev/null +++ b/ci-scripts/docker_log_split.py @@ -0,0 +1,92 @@ +#/* +# * 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 +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + + +#----------------------------------------------------------- +# Import Libs +#----------------------------------------------------------- +import sys # arg +import re # reg +import os +import subprocess + + +class SplitReport(): + def __init__(self): + self.logfilename = '' + self.destinationFolder = '' + + def split(self): + self.destinationFolder = self.logfilename.replace(".log","") + if os.path.isfile(self.logfilename): + newImageLog = open(self.logfilename + '.new', 'w') + copyFlag = True + with open(self.logfilename, 'r') as imageLog: + for line in imageLog: + header = False + ret = re.search('====== Start of log for ([0-9\.A-Za-z\-\_]+) ======', line) + if ret is not None: + copyFlag = False + header = True + detailedLogFile = open(self.destinationFolder + '/' + ret.group(1), 'w') + if copyFlag: + newImageLog.write(line) + ret = re.search('====== End of log for ([0-9\.A-Za-z\-\_]+) ======', line) + if ret is not None: + copyFlag = True + detailedLogFile.close() + elif not copyFlag and not header: + detailedLogFile.write(line) + imageLog.close() + newImageLog.close() + os.rename(self.logfilename + '.new', self.logfilename) + else: + print('Cannot split unfound file') + +#-------------------------------------------------------------------------------------------------------- +# +# Start of main +# +#-------------------------------------------------------------------------------------------------------- + +argvs = sys.argv +argc = len(argvs) + +SP = SplitReport() + +while len(argvs) > 1: + myArgv = argvs.pop(1) + if re.match('^\-\-logfilename=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-logfilename=(.+)$', myArgv, re.IGNORECASE) + SP.logfilename = matchReg.group(1) + +SP.split() + +sys.exit(0) diff --git a/ci-scripts/oai-ci-vm-tool b/ci-scripts/oai-ci-vm-tool index 9b9fe462f1..d8f088b707 100755 --- a/ci-scripts/oai-ci-vm-tool +++ b/ci-scripts/oai-ci-vm-tool @@ -172,6 +172,7 @@ function setvar_usage { function variant__v1__enb_usrp { NB_PATTERN_FILES=9 BUILD_OPTIONS="--eNB -w USRP --mu" + VM_MEMORY=3072 } function variant__v2__basic_sim { @@ -213,15 +214,15 @@ function variant__v6__nr_ue_usrp { function variant__v7__enb_ethernet { VM_MEMORY=4096 ARCHIVES_LOC=enb_eth - NB_PATTERN_FILES=8 - BUILD_OPTIONS="--eNB" + NB_PATTERN_FILES=9 + BUILD_OPTIONS="--eNB -w USRP" } function variant__v8__ue_ethernet { VM_MEMORY=4096 ARCHIVES_LOC=ue_eth - NB_PATTERN_FILES=12 - BUILD_OPTIONS="--UE" + NB_PATTERN_FILES=13 + BUILD_OPTIONS="--UE -w USRP" } function variant__v10__flexran_rtc { diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 774d7f19c6..783adb98e6 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -239,6 +239,7 @@ class RANManagement(): while (count > 0) and buildOAIprocess: mySSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 6) result = re.search('build_oai', mySSH.getBefore()) + print(result) if result is None: buildOAIprocess = False else: @@ -464,7 +465,7 @@ class RANManagement(): self.prematureExit = True return else: - mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting|Started"', '\$', 4) if rruCheck: result = re.search('wait RUs', mySSH.getBefore()) else: diff --git a/ci-scripts/reportBuildLocally.sh b/ci-scripts/reportBuildLocally.sh index 44d200c3b6..19a486303f 100755 --- a/ci-scripts/reportBuildLocally.sh +++ b/ci-scripts/reportBuildLocally.sh @@ -580,16 +580,42 @@ function report_build { sca_summary_table_row ./archives/cppcheck/cppcheck.xml "Expression depends on order of evaluation of side effects" unknownEvaluationOrder sca_summary_table_footer ./archives/cppcheck/cppcheck.xml - summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_usrp - summary_table_row "LTE SoftModem - Release 15" ./archives/enb_usrp/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_usrp_row1.html - summary_table_row "Coding - Release 15" ./archives/enb_usrp/coding.Rel15.txt "Built target coding" ./enb_usrp_row2.html - summary_table_row "OAI USRP device if - Release 15" ./archives/enb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_usrp_row3.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_usrp_row4.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_usrp_row5.html - summary_table_row "NASMESH - Release 15" ./archives/enb_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./enb_usrp_row6.html - summary_table_row "RB Tool - Release 15" ./archives/enb_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./enb_usrp_row7.html - summary_table_row "RF Simulator - Release 15" ./archives/enb_usrp/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_usrp_row8.html - summary_table_row "TCP Bridge - Release 15" ./archives/enb_usrp/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_usrp_row9.html +# summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_usrp +# summary_table_row "LTE SoftModem - Release 15" ./archives/enb_usrp/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_usrp_row1.html +# summary_table_row "Coding - Release 15" ./archives/enb_usrp/coding.Rel15.txt "Built target coding" ./enb_usrp_row2.html +# summary_table_row "OAI USRP device if - Release 15" ./archives/enb_usrp/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_usrp_row3.html +# summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_usrp/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_usrp_row4.html +# summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_usrp/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_usrp_row5.html +# summary_table_row "NASMESH - Release 15" ./archives/enb_usrp/nasmesh.Rel15.txt "Built target nasmesh" ./enb_usrp_row6.html +# summary_table_row "RB Tool - Release 15" ./archives/enb_usrp/rb_tool.Rel15.txt "Built target rb_tool" ./enb_usrp_row7.html +# summary_table_row "RF Simulator - Release 15" ./archives/enb_usrp/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_usrp_row8.html +# summary_table_row "TCP Bridge - Release 15" ./archives/enb_usrp/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_usrp_row9.html +# summary_table_footer +# + summary_table_header "OAI Build: 4G LTE eNB -- USRP option" ./archives/enb_eth + summary_table_row "LTE SoftModem - Release 15" ./archives/enb_eth/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_eth_row1.html + summary_table_row "Coding - Release 15" ./archives/enb_eth/coding.Rel15.txt "Built target coding" ./enb_eth_row2.html + summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_eth_row3.html + summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_eth_row4.html + summary_table_row "RF Simulator - Release 15" ./archives/enb_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_eth_row5.html + summary_table_row "TCP OAI Bridge - Release 15" ./archives/enb_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_eth_row6.html + summary_table_row "OAI USRP device if - Release 15" ./archives/enb_eth/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./enb_eth_row7.html + summary_table_row "NASMESH - Release 15" ./archives/enb_eth/nasmesh.Rel15.txt "Built target nasmesh" ./enb_eth_row8.html + summary_table_row "RB Tool - Release 15" ./archives/enb_eth/rb_tool.Rel15.txt "Built target rb_tool" ./enb_eth_row9.html + summary_table_footer + + summary_table_header "OAI Build: 4G LTE UE -- USRP option" ./archives/ue_eth + summary_table_row "LTE UE SoftModem - Release 15" ./archives/ue_eth/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./ue_eth_row1.html + summary_table_row "Coding - Release 15" ./archives/ue_eth/coding.Rel15.txt "Built target coding" ./ue_eth_row2.html + summary_table_row "OAI ETHERNET transport - Release 15" ./archives/ue_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./ue_eth_row3.html + summary_table_row "Parameters Lib Config - Release 15" ./archives/ue_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./ue_eth_row4.html + summary_table_row "RF Simulator - Release 15" ./archives/ue_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./ue_eth_row5.html + summary_table_row "TCP OAI Bridge - Release 15" ./archives/ue_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./ue_eth_row6.html + summary_table_row "Conf 2 UE Data - Release 15" ./archives/ue_eth/conf2uedata.Rel15.txt "Built target conf2uedata" ./ue_eth_row7.html + summary_table_row "NVRAM - Release 15" ./archives/ue_eth/nvram.Rel15.txt "Built target nvram" ./ue_eth_row8.html + summary_table_row "UE IP - Release 15" ./archives/ue_eth/ue_ip.Rel15.txt "Built target ue_ip" ./ue_eth_row9.html + summary_table_row "USIM - Release 15" ./archives/ue_eth/usim.Rel15.txt "Built target usim" ./ue_eth_row9a.html + summary_table_row "OAI USRP device if - Release 15" ./archives/ue_eth/oai_usrpdevif.Rel15.txt "Built target oai_usrpdevif" ./ue_eth_row9b.html summary_table_footer summary_table_header "OAI Build: 4G LTE basic simulator option" ./archives/basic_sim @@ -676,28 +702,6 @@ function report_build { summary_table_footer fi - summary_table_header "OAI Build: 4G LTE eNB -- ETHERNET transport option" ./archives/enb_eth - summary_table_row "LTE SoftModem - Release 15" ./archives/enb_eth/lte-softmodem.Rel15.txt "Built target lte-softmodem" ./enb_eth_row1.html - summary_table_row "Coding - Release 15" ./archives/enb_eth/coding.Rel15.txt "Built target coding" ./enb_eth_row2.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/enb_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./enb_eth_row3.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/enb_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./enb_eth_row4.html - summary_table_row "RF Simulator - Release 15" ./archives/enb_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./enb_eth_row5.html - summary_table_row "TCP OAI Bridge - Release 15" ./archives/enb_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./enb_eth_row6.html - summary_table_footer - - summary_table_header "OAI Build: 4G LTE UE -- ETHERNET transport option" ./archives/ue_eth - summary_table_row "LTE UE SoftModem - Release 15" ./archives/ue_eth/lte-uesoftmodem.Rel15.txt "Built target lte-uesoftmodem" ./ue_eth_row1.html - summary_table_row "Coding - Release 15" ./archives/ue_eth/coding.Rel15.txt "Built target coding" ./ue_eth_row2.html - summary_table_row "OAI ETHERNET transport - Release 15" ./archives/ue_eth/oai_eth_transpro.Rel15.txt "Built target oai_eth_transpro" ./ue_eth_row3.html - summary_table_row "Parameters Lib Config - Release 15" ./archives/ue_eth/params_libconfig.Rel15.txt "Built target params_libconfig" ./ue_eth_row4.html - summary_table_row "RF Simulator - Release 15" ./archives/ue_eth/rfsimulator.Rel15.txt "Built target rfsimulator" ./ue_eth_row5.html - summary_table_row "TCP OAI Bridge - Release 15" ./archives/ue_eth/tcp_bridge_oai.Rel15.txt "Built target tcp_bridge_oai" ./ue_eth_row6.html - summary_table_row "Conf 2 UE Data - Release 15" ./archives/ue_eth/conf2uedata.Rel15.txt "Built target conf2uedata" ./ue_eth_row7.html - summary_table_row "NVRAM - Release 15" ./archives/ue_eth/nvram.Rel15.txt "Built target nvram" ./ue_eth_row8.html - summary_table_row "UE IP - Release 15" ./archives/ue_eth/ue_ip.Rel15.txt "Built target ue_ip" ./ue_eth_row9.html - summary_table_row "USIM - Release 15" ./archives/ue_eth/usim.Rel15.txt "Built target usim" ./ue_eth_row9a.html - summary_table_footer - if [ -e ./archives/red_hat ] then echo "

Red Hat Enterprise Linux Server release 7.6) -- Summary

" >> ./build_results.html @@ -714,9 +718,23 @@ function report_build { echo " " >> ./build_results.html echo "
" >> ./build_results.html - if [ -f ./enb_usrp_row1.html ] || [ -f ./enb_usrp_row2.html ] || [ -f ./enb_usrp_row3.html ] || [ -f ./enb_usrp_row4.html ] +# if [ -f ./enb_usrp_row1.html ] || [ -f ./enb_usrp_row2.html ] || [ -f ./enb_usrp_row3.html ] || [ -f ./enb_usrp_row4.html ] +# then +# for DETAILS_TABLE in `ls ./enb_usrp_row*.html` +# do +# cat $DETAILS_TABLE >> ./build_results.html +# done +# fi + if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ] || [ -f ./enb_eth_row7.html ] || [ -f ./enb_eth_row8.html ] || [ -f ./enb_eth_row9.html ] then - for DETAILS_TABLE in `ls ./enb_usrp_row*.html` + for DETAILS_TABLE in `ls ./enb_eth_row*.html` + do + cat $DETAILS_TABLE >> ./build_results.html + done + fi + if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ] || [ -f ./ue_eth_row7.html ] || [ -f ./ue_eth_row8.html ] || [ -f ./ue_eth_row9.html ] || [ -f ./ue_eth_row9a.html ] || [ -f ./ue_eth_row9b.html ] + then + for DETAILS_TABLE in `ls ./ue_eth_row*.html` do cat $DETAILS_TABLE >> ./build_results.html done @@ -749,20 +767,6 @@ function report_build { cat $DETAILS_TABLE >> ./build_results.html done fi - if [ -f ./enb_eth_row1.html ] || [ -f ./enb_eth_row2.html ] || [ -f ./enb_eth_row3.html ] || [ -f ./enb_eth_row4.html ] || [ -f ./enb_eth_row5.html ] || [ -f ./enb_eth_row6.html ] - then - for DETAILS_TABLE in `ls ./enb_eth_row*.html` - do - cat $DETAILS_TABLE >> ./build_results.html - done - fi - if [ -f ./ue_eth_row1.html ] || [ -f ./ue_eth_row2.html ] || [ -f ./ue_eth_row3.html ] || [ -f ./ue_eth_row4.html ] || [ -f ./ue_eth_row5.html ] || [ -f ./ue_eth_row6.html ] - then - for DETAILS_TABLE in `ls ./ue_eth_row*.html` - do - cat $DETAILS_TABLE >> ./build_results.html - done - fi if [ -f ./enb_usrp_rh_row1.html ] || [ -f ./enb_usrp_rh_row2.html ] || [ -f ./enb_usrp_rh_row3.html ] || [ -f ./enb_usrp_rh_row4.html ] then for DETAILS_TABLE in `ls ./enb_usrp_rh_row*.html` diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh index 8562f4b2de..415ded57a4 100755 --- a/ci-scripts/reportTestLocally.sh +++ b/ci-scripts/reportTestLocally.sh @@ -749,7 +749,7 @@ function report_test { echo " " >> ./test_simulator_results.html EPC_CONFIGS=("noS1") - TRANS_MODES=("tdd") + TRANS_MODES=("fdd" "tdd") BW_CASES=(106) for CN_CONFIG in ${EPC_CONFIGS[@]} do diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 70eabb7b69..f818685049 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -379,7 +379,7 @@ function check_iperf { local LOC_IS_DL=`echo $LOC_BASE_LOG | grep -c _dl` local LOC_IS_BASIC_SIM=`echo $LOC_BASE_LOG | grep -c basic_sim` local LOC_IS_RF_SIM=`echo $LOC_BASE_LOG | grep -c rf_sim` - local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c tdd_106prb` + local LOC_IS_NR=`echo $LOC_BASE_LOG | grep -c _106prb` if [ -f ${LOC_BASE_LOG}_client.txt ] then local FILE_COMPLETE=`egrep -c "Server Report" ${LOC_BASE_LOG}_client.txt` @@ -2189,39 +2189,50 @@ function run_test_on_vm { if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]] then - CN_CONFIG="noS1" - CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf - S1_NOS1_CFG=0 - PRB=106 - FREQUENCY=3510 - if [ ! -d $ARCHIVES_LOC ] then mkdir --parents $ARCHIVES_LOC fi - local try_cnt=0 - NR_STATUS=0 + CN_CONFIG="noS1" + S1_NOS1_CFG=0 ######### start of RA TEST loop - while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI + # for the moment only TDD + TRANS_MODES=("tdd") + for TMODE in ${TRANS_MODES[@]} do + if [[ $TMODE =~ .*fdd.* ]] + then + CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=37000 + else + CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=3510 + fi + local try_cnt=0 + NR_STATUS=0 + while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI + + do SYNC_STATUS=0 RA_STATUS=0 - rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}*ra_test.log + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}*ra_test.log echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB" + echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (RA TEST)" echo "############################################################" - CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log + CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb_ra_test.log #last argument = 1 is to enable --do-ra for RA test start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1 echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE" + echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (RA TEST)" echo "############################################################" - CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue_ra_test.log + CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue_ra_test.log #last argument = 1 is to enable --do-ra for RA test start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1 if [ $NR_UE_SYNC -eq 0 ] @@ -2260,35 +2271,47 @@ function run_test_on_vm { else try_cnt=$((try_cnt+10)) fi + done done ########### end RA test sleep 30 - ######### start of PHY TEST loop - try_cnt=0 - while [ $try_cnt -lt 4 ] + SYNC_STATUS=0 + PING_STATUS=0 + IPERF_STATUS=0 + TRANS_MODES=("fdd tdd") + for TMODE in ${TRANS_MODES[@]} do + if [[ $TMODE =~ .*fdd.* ]] + then + CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=37000 + else + CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf + PRB=106 + FREQUENCY=3510 + fi - - SYNC_STATUS=0 - PING_STATUS=0 - IPERF_STATUS=0 - rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ue.log - rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log - rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}_iperf_ul*txt + try_cnt=0 + while [ $try_cnt -lt 4 ] + do + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log + rm -f $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl*txt $ARCHIVES_LOC/${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul*txt echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB" + echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (PHY TEST)" echo "############################################################" - CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log + CURRENT_GNB_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_gnb.log start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 0 echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE" + echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (PHY TEST)" echo "############################################################" - CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log + CURRENT_NR_UE_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ue.log start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 0 if [ $NR_UE_SYNC -eq 0 ] then @@ -2306,7 +2329,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : Pinging the gNB from NR-UE" echo "############################################################" get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR - PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log + PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log ping_epc_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $ENB_IP_ADDR $PING_LOG_FILE 1 0 scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 @@ -2315,7 +2338,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : Pinging the NR-UE from gNB" echo "############################################################" get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 - PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log + PING_LOG_FILE=${TMODE}_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log ping_enb_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR $UE_IP_ADDR $PING_LOG_FILE 0 scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 @@ -2324,7 +2347,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client" echo "############################################################" THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl + CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_dl get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 @@ -2346,7 +2369,7 @@ function run_test_on_vm { echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client" echo "############################################################" THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul + CURR_IPERF_LOG_BASE=${TMODE}_${PRB}prb_${CN_CONFIG}_iperf_ul get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 @@ -2368,6 +2391,7 @@ function run_test_on_vm { else try_cnt=$((try_cnt+10)) fi + done done ######### end of loop full_l2_sim_destroy diff --git a/ci-scripts/waitBuildOnVM.sh b/ci-scripts/waitBuildOnVM.sh index f066dacd81..ff2129a187 100755 --- a/ci-scripts/waitBuildOnVM.sh +++ b/ci-scripts/waitBuildOnVM.sh @@ -47,6 +47,12 @@ function wait_on_vm_build { echo "ARCHIVES_LOC = $ARCHIVES_LOC" echo "BUILD_OPTIONS = $BUILD_OPTIONS" + if [[ "$VM_NAME" == *"-enb-usrp"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + IS_VM_ALIVE=`uvt-kvm list | grep -c $VM_NAME` if [ $IS_VM_ALIVE -eq 0 ] @@ -84,6 +90,12 @@ function wait_on_vm_build { } function check_on_vm_build { + if [[ "$VM_NAME" == *"-enb-usrp"* ]] + then + echo "This VM type is no longer supported in the pipeline framework" + return + fi + echo "############################################################" echo "Creating a tmp folder to store results and artifacts" echo "############################################################" diff --git a/ci-scripts/xml_files/fr1_multi_node_test.xml b/ci-scripts/xml_files/benetel_multi_node_build.xml similarity index 50% rename from ci-scripts/xml_files/fr1_multi_node_test.xml rename to ci-scripts/xml_files/benetel_multi_node_build.xml index 8c56f0bcec..5ac28951b4 100644 --- a/ci-scripts/xml_files/fr1_multi_node_test.xml +++ b/ci-scripts/xml_files/benetel_multi_node_build.xml @@ -21,57 +21,34 @@ --> - test-fr1-tm1 - Test-FR1-TM1 - tasks - 1 + build-tab + Build + wrench - 030000 - 040000 - 000001 - 070001 - 070000 + 000001 000002 - - - - - Initialize_eNB - Initialize eNB - -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf - 0 - 0 - lte - - - - Initialize_eNB - Initialize gNB (3/4 sampling rate) - -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E - 1 - 1 - nr - + - IdleSleep - Sleep - 30 - - - - Terminate_eNB - Terminate eNB + Build_eNB + Build eNB + --eNB -t benetel4g -w None + True 0 0 - - Terminate_eNB - Terminate gNB + + + Build_eNB + Build gNB + --gNB -t benetel5g -w None + True 1 1 - + + + diff --git a/ci-scripts/xml_files/benetel_nsa_base.xml b/ci-scripts/xml_files/benetel_nsa_base.xml new file mode 100644 index 0000000000..0aed28dffa --- /dev/null +++ b/ci-scripts/xml_files/benetel_nsa_base.xml @@ -0,0 +1,162 @@ + + + TEST-FR1-TM1 + FR1 + tasks + + 010000 + 030000 + 040000 + 010001 + 000001 + 050000 + 050001 + 000001 + 060000 + 060001 + 000001 + 070000 + 070001 + 010002 + 000001 + 080001 + 080000 + 010003 + + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/benetel-4g.conf + 0 + 0 + lte + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/benetel-5g.conf + 1 + 1 + nr + + + + IdleSleep + Sleep + 20 + + + + Ping + Ping: 20pings in 20sec + -c 20 + 50 + + + + Ping + Ping: 100pings in 20sec + -c 100 -i 0.2 + 50 + + + + + Iperf + iperf (DL/2.5Mbps/UDP)(60 sec)(single-ue profile) + -u -b 2.5M -t 60 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/1.5Mbps/UDP)(60 sec)(single-ue profile) + -u -b 1.5M -t 60 -i 1 -R + 50 + single-ue + + + + + Iperf + iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) + -u -b 20M -t 20 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 -R + 50 + single-ue + + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_image_build.xml b/ci-scripts/xml_files/container_image_build.xml similarity index 93% rename from ci-scripts/xml_files/fr1_image_build.xml rename to ci-scripts/xml_files/container_image_build.xml index 9dd386b646..430729c49c 100644 --- a/ci-scripts/xml_files/fr1_image_build.xml +++ b/ci-scripts/xml_files/container_image_build.xml @@ -22,7 +22,7 @@ --> build-tab - Build + Build Container Images wrench 000001 @@ -31,7 +31,7 @@ Build_Image - Build eNB Image + Build all Images all 0 0 diff --git a/ci-scripts/xml_files/fr1_multi_node_build.xml b/ci-scripts/xml_files/fr1_multi_node_build.xml index 7b4eacef3a..57c4685341 100644 --- a/ci-scripts/xml_files/fr1_multi_node_build.xml +++ b/ci-scripts/xml_files/fr1_multi_node_build.xml @@ -37,6 +37,7 @@ 0 0 True + True @@ -53,6 +54,7 @@ 1 1 True + True diff --git a/ci-scripts/xml_files/fr1_ran_ue_iperf.xml b/ci-scripts/xml_files/fr1_nsa_base.xml similarity index 80% rename from ci-scripts/xml_files/fr1_ran_ue_iperf.xml rename to ci-scripts/xml_files/fr1_nsa_base.xml index 8ead3afc62..96bdc79f0f 100644 --- a/ci-scripts/xml_files/fr1_ran_ue_iperf.xml +++ b/ci-scripts/xml_files/fr1_nsa_base.xml @@ -21,8 +21,8 @@ --> - TEST-FR1-TM1 - FR1 + TEST-NSA-FR1-TM1 + NSA FULL tasks 010000 @@ -31,14 +31,17 @@ 010001 000001 050000 + 050001 000001 060000 060001 000001 + 070000 + 070001 010002 000001 - 070001 - 070000 + 080001 + 080000 010003 @@ -96,6 +99,13 @@ 50 + + Ping + Ping: 100pings in 20sec + -c 100 -i 0.2 + 50 + + Iperf @@ -113,7 +123,26 @@ single-ue + + Iperf + iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) + -u -b 20M -t 20 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 -R + 50 + single-ue + + + + + Terminate_eNB Terminate eNB 0 @@ -121,7 +150,7 @@ lte - + Terminate_eNB Terminate gNB 1 diff --git a/ci-scripts/xml_files/fr1_ran_ue_base.xml b/ci-scripts/xml_files/fr1_nsa_base_ref.xml similarity index 80% rename from ci-scripts/xml_files/fr1_ran_ue_base.xml rename to ci-scripts/xml_files/fr1_nsa_base_ref.xml index 847967f81e..fd47db10b2 100644 --- a/ci-scripts/xml_files/fr1_ran_ue_base.xml +++ b/ci-scripts/xml_files/fr1_nsa_base_ref.xml @@ -21,8 +21,8 @@ --> - TEST-FR1-TM1 - FR1 + TEST-NSA-FR1-TM1 + NSA FULL tasks 010000 @@ -32,16 +32,15 @@ 000001 050000 050001 - 050002 - 050002 000001 060000 060001 000001 + 070000 010002 000001 - 070001 - 070000 + 080001 + 080000 010003 @@ -100,13 +99,6 @@ - Ping - Ping: 5pings in 1sec - -c 5 -i 0.2 - 50 - - - Ping Ping: 100pings in 20sec -c 100 -i 0.2 @@ -116,21 +108,40 @@ Iperf - iperf (DL/1Mbps/UDP)(30 sec)(single-ue profile) - -u -b 1M -t 30 -i 1 + iperf (DL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 50 single-ue Iperf - iperf (UL/1Mbps/UDP)(30 sec)(single-ue profile) - -u -b 1M -t 30 -i 1 -R + iperf (UL/1Mbps/UDP)(20 sec)(single-ue profile) + -u -b 1M -t 20 -i 1 -R 50 single-ue + + Iperf + iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) + -u -b 20M -t 20 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) + -u -b 3M -t 20 -i 1 -R + 50 + single-ue + + + + + Terminate_eNB Terminate eNB 0 @@ -138,7 +149,7 @@ lte - + Terminate_eNB Terminate gNB 1 diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index e11c850b8e..626d938625 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -926,6 +926,9 @@ set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidd # Benetel 4G library ###################################################################### + +include_directories ("/usr/include/dpdk") + set(HWLIB_BENETEL_4G_SOURCE ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/benetel.c ${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/shared_buffers.c @@ -1967,7 +1970,8 @@ set(NR_PDCP_SRC ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c - ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_sdu.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c ) @@ -3141,7 +3145,7 @@ target_link_libraries (nr-uesoftmodem RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB - ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} NFAPI_USER_LIB S1AP_LIB S1AP_ENB ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB -Wl,--end-group z dl) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 089d0503fd..016c76dc06 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1294,7 +1294,8 @@ (Test10: SC-FDMA, 75 PRBs), (Test11: SC-FDMA, 216 PRBs), (Test12: SC-FDMA, 273 PRBs), - (Test13: SC-FDMA, 3 DMRS) + (Test13: SC-FDMA, 3 DMRS), + (Test14: MCS 16 50 PRBs 2 RX_Antenna) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1313,9 +1314,10 @@ -n100 -s2 -Z -r75 -n100 -s2 -Z -r216 -R217 -n100 -s2 -Z -r270 -R273 - -n100 -s2 -Z -U 2 0 2 + -n100 -s2 -Z -U 2 0 2 + -n100 -m16 -s10 -z2 - nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13 + nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13 nr_ulsim.test14 PUSCH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 960b241047..dba6d7da6d 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -48,8 +48,9 @@ DEADLINE_SCHEDULER_FLAG_USER="" CPU_AFFINITY_FLAG_USER="False" #Only valid when low-latency flag is set to False REL="Rel15" HW="None" -TP="None" +TP="Ethernet" EPC=0 +VERBOSE_CI=0 VERBOSE_COMPILE=0 CFLAGS_PROCESSOR_USER="" RUN_GROUP=0 @@ -289,6 +290,9 @@ function main() { esac echo_info "Setting hardware to: $HW" shift 2;; + -t | --transport) + TP=$2 + shift 2;; -P | --phy_simulators) SIMUS_PHY=1 echo_info "Will compile dlsim, ulsim, ..." @@ -324,6 +328,10 @@ function main() { HWLAT_TEST=1 echo_info "Will compile hw latency test program" shift;; + --verbose-ci) + VERBOSE_CI=1 + echo_info "Will compile with verbose instructions in CI Docker env" + shift;; --verbose-compile) VERBOSE_COMPILE=1 echo_info "Will compile with verbose instructions" @@ -936,12 +944,30 @@ function main() { echo_info "Building transport protocol libraries" rm -f liboai_transpro.so rm -f $dbin/liboai_transpro.so - compilations \ - $build_dir oai_eth_transpro \ - liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL - ln -sf liboai_eth_transpro.so liboai_transpro.so - ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so - echo_info "liboai_transpro.so is linked to ETHERNET transport" + if [ "$TP" == "Ethernet" ]; then + compilations \ + $build_dir oai_eth_transpro \ + liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL + ln -sf liboai_eth_transpro.so liboai_transpro.so + ln -sf $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to ETHERNET transport" + fi + if [ "$TP" == "benetel4g" ]; then + compilations \ + $build_dir benetel_4g \ + libbenetel_4g.so $dbin/libbenetel_4g.$REL + ln -sf libbenetel_4g.so liboai_transpro.so + ln -sf $dbin/libbenetel_4g.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to BENETEL4G transport" + fi + if [ "$TP" == "benetel5g" ]; then + compilations \ + $build_dir benetel_5g \ + libbenetel_5g.so $dbin/libbenetel_5g.$REL + ln -sf libbenetel_5g.so liboai_transpro.so + ln -sf $dbin/libbenetel_5g.so.$REL $dbin/liboai_transpro.so + echo_info "liboai_transpro.so is linked to BENETEL4G transport" + fi fi fi diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 674d4a0cac..9b8363fc2b 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -41,7 +41,7 @@ KERNEL_VERSION=$(uname -r | cut -d '.' -f1) KERNEL_MAJOR=$(uname -r | cut -d '.' -f2) #check if we run inside a container -IS_CONTAINER=`egrep -c "docker|podman|kubepods" /proc/self/cgroup || true` +IS_CONTAINER=`egrep -c "docker|podman|kubepods|libpod|buildah" /proc/self/cgroup || true` #sudo is not needed when we are root if [ "$UID" = 0 ] then @@ -221,6 +221,11 @@ compilations() { ret=$? } > $dlog/$2.$REL.txt 2>&1 set -e + if [ "$VERBOSE_CI" == "1" ]; then + echo_info "====== Start of log for $2.$REL.txt ======" + cat $dlog/$2.$REL.txt + echo_info "====== End of log for $2.$REL.txt ======" + fi if [[ $ret -ne 0 ]]; then check_warnings "$dlog/$2.$REL.txt" check_errors "$dlog/$2.$REL.txt" @@ -273,6 +278,10 @@ install_protobuf_from_source(){ make -j`nproc` $SUDO make install $SUDO ldconfig + if [[ -v CI_ENV ]]; then + cd /tmp + $SUDO rm -rf protobuf* + fi ) >& $protobuf_install_log } @@ -295,6 +304,10 @@ install_protobuf_c_from_source(){ make -j`nproc` $SUDO make install $SUDO ldconfig + if [[ -v CI_ENV ]]; then + cd /tmp + $SUDO rm -rf protobuf* + fi ) >& $protobuf_c_install_log } @@ -351,10 +364,10 @@ check_install_usrp_uhd_driver(){ elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then if [ $IS_CONTAINER -eq 0 ] then - $SUDO $INSTALLER -y install python boost libusb-devel libusbx-devel boost-devel python-mako python-docutils cmake + $SUDO $INSTALLER -y install python boost libusb-devel libusbx-devel boost-devel python-mako python-docutils $CMAKE $SUDO -H pip install requests else - $SUDO $INSTALLER -y install boost boost-devel cmake3 + $SUDO $INSTALLER -y install boost boost-devel $CMAKE $SUDO pip3 install mako requests fi if [[ "$OS_DISTRO" == "rhel" ]] || [[ "$OS_DISTRO" == "centos" ]]; then @@ -480,7 +493,7 @@ install_soapy_from_source(){ #git checkout tags/release_003_010_001_001 mkdir -p build cd build - cmake ../ + $CMAKE ../ echo "Compiling SoapyRemote" make -j`nproc` $SUDO make install @@ -499,7 +512,7 @@ install_soapy_iris_from_source(){ cd sklk-soapyiris mkdir -p build cd build - cmake ../ + $CMAKE ../ echo "Compiling SoapyIris" make -j`nproc` $SUDO make install @@ -676,7 +689,7 @@ check_install_oai_software() { automake \ bison \ build-essential \ - cmake \ + $CMAKE \ cmake-curses-gui \ ninja-build \ doxygen \ @@ -831,6 +844,9 @@ install_asn1c_from_source(){ $SUDO make install cd - $SUDO ldconfig + if [[ -v CI_ENV ]]; then + $SUDO rm -rf /tmp/asn1c + fi ) > $asn1_install_log 2>&1 } diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index 9fd67a6dbb..4e6ec9d3db 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -88,7 +88,8 @@ int write_file_matlab(const char *fname, void *data, int length, int dec, - unsigned int format) + unsigned int format, + int multiVec) { FILE *fp=NULL; int i; @@ -100,8 +101,7 @@ int write_file_matlab(const char *fname, //printf("Writing %d elements of type %d to %s\n",length,format,fname); - - if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) { + if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) { fp = fopen(fname,"a+"); } else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) { fp = fopen(fname,"w+"); @@ -137,8 +137,7 @@ int write_file_matlab(const char *fname, return(0); } - - if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) + if ((format != 10 && format !=11 && format != 12 && format != 13 && format != 14) || multiVec) fprintf(fp,"%s = [",vname); switch (format) { @@ -247,7 +246,7 @@ int write_file_matlab(const char *fname, AssertFatal(false, "unknown dump format: %d\n", format); } - if (format != 10 && format !=11 && format !=12 && format != 13 && format != 15) { + if ((format != 10 && format !=11 && format !=12 && format != 13 && format != 15) || multiVec) { fprintf(fp,"];\n"); fclose(fp); return(0); diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index 49c6bdfd4c..0cbae7ae2c 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -335,6 +335,7 @@ typedef struct { @param length length of data vector to output @param dec decimation level @param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit) +@param multiVec create new file or append to existing (useful for writing multiple vectors to same file. Just call the function multiple times with same file name and with this parameter set to 1) */ #define MATLAB_RAW (1<<31) #define MATLAB_SHORT 0 @@ -354,7 +355,7 @@ typedef struct { #define MATLAB_CSHORT_BRACKET2 14 #define MATLAB_CSHORT_BRACKET3 15 -int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format); +int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format, int multiVec); /*----------------macro definitions for reading log configuration from the config module */ #define CONFIG_STRING_LOG_PREFIX "log_config" @@ -414,7 +415,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int /* bitmask dependent macros, to generate debug file such as matlab file or message dump */ # define LOG_DUMPFLAG(D) (g_log->dump_mask & D) -# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)/* */ +# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0)/* */ /* define variable only used in LOG macro's */ # define LOG_VAR(A,B) A B # else /* T_TRACER: remove all debugging and tracing messages, except errors */ @@ -431,7 +432,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int # define LOG_DUMPFLAG(D) (g_log->debug_mask & D) # define LOG_DUMPMSG(c, f, b, s, x...) do { if(g_log->dump_mask & f) log_dump(c, b, s, LOG_DUMP_CHAR, x) ;} while (0) /* */ -# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0) +# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0) # define LOG_VAR(A,B) A B # endif /* T_TRACER */ /* avoid warnings for variables only used in LOG macro's but set outside debug section */ @@ -439,9 +440,10 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int #define LOG_USEDINLOG_VAR(A,B) GCC_NOTUSED A B /* unfiltered macros, useful for simulators or messages at init time, before log is configured */ -#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0) +#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 0);} while(0) #define LOG_UI(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ; } while(0) #define LOG_UDUMPMSG(c, b, s, f, x...) do { log_dump(c, b, s, f, x) ;} while (0) /* */ +# define LOG_MM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format, 1);} while(0) /* @}*/ diff --git a/common/utils/T/.gitignore b/common/utils/T/.gitignore index d754ff7c38..6a6e5817c5 100644 --- a/common/utils/T/.gitignore +++ b/common/utils/T/.gitignore @@ -4,6 +4,7 @@ T_IDs.h T_messages.txt.h genids tracer/enb +tracer/gnb tracer/extract_config tracer/record tracer/replay diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index bad6444e13..fedc50cf5d 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -1,7 +1,3 @@ -ID = BENETEL - GROUP = ALL - FORMAT = int,frame : int,slot : buffer,rxdataF - #general logs ID = ENB_MASTER_TICK DESC = eNodeB master tick - one tick per ms, to be used as "reference clock", mostly for ticktime view @@ -93,6 +89,10 @@ ID = GNB_PHY_MIB DESC = NR MIB data GROUP = ALL:PHY:GNB:WIRESHARK FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data +ID = GNB_PHY_PUCCH_PUSCH_IQ + DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done + GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB + FORMAT = int,frame : int,slot : buffer,rxdataF #MAC logs ID = ENB_MAC_UE_DL_SDU diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile index 792c2a407c..0713d9a3df 100644 --- a/common/utils/T/tracer/Makefile +++ b/common/utils/T/tracer/Makefile @@ -7,7 +7,8 @@ LIBS=-lm XLIBS=-lX11 -lpng -lXft all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ - extract_input_subframe extract_output_subframe to_vcd extract multi + extract_input_subframe extract_output_subframe to_vcd extract multi \ + gnb record: utils.o record.o database.o config.o $(CC) $(CFLAGS) -o record $^ $(LIBS) @@ -60,6 +61,11 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \ multi: multi.o utils.o database.o config.o $(CC) $(CFLAGS) -o multi $^ $(LIBS) +gnb: utils.o gnb.o database.o event.o handler.o config.o \ + view/view.a gui/gui.a logger/logger.a \ + filter/filter.a + $(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS) + multi.o: ../T_IDs.h ../T_IDs.h: @@ -85,7 +91,7 @@ filter/filter.a: clean: rm -f *.o core tracer_remote textlog enb ue vcd record replay rm -f extract_config macpdu2wireshark extract_input_subframe - rm -f extract_output_subframe to_vcd extract multi + rm -f extract_output_subframe to_vcd extract multi gnb cd gui && $(MAKE) clean cd view && $(MAKE) clean cd logger && $(MAKE) clean diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c new file mode 100644 index 0000000000..4aaa4898a1 --- /dev/null +++ b/common/utils/T/tracer/gnb.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include "database.h" +#include "handler.h" +#include "config.h" +#include "logger/logger.h" +#include "view/view.h" +#include "gui/gui.h" + +typedef struct { + widget *pucch_pusch_iq_plot; + logger *pucch_pusch_iq_logger; +} gnb_gui; + +typedef struct { + int socket; + int *is_on; + int nevents; + pthread_mutex_t lock; + gnb_gui *e; + void *database; +} gnb_data; + +void is_on_changed(void *_d) +{ + gnb_data *d = _d; + char t; + + if (pthread_mutex_lock(&d->lock)) abort(); + + if (d->socket == -1) goto no_connection; + + t = 1; + if (socket_send(d->socket, &t, 1) == -1 || + socket_send(d->socket, &d->nevents, sizeof(int)) == -1 || + socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1) + goto connection_dies; + +no_connection: + if (pthread_mutex_unlock(&d->lock)) abort(); + return; + +connection_dies: + close(d->socket); + d->socket = -1; + if (pthread_mutex_unlock(&d->lock)) abort(); +} + +void usage(void) +{ + printf( +"options:\n" +" -d this option is mandatory\n" +" -ip connect to given IP address (default %s)\n" +" -p connect to given port (default %d)\n", + DEFAULT_REMOTE_IP, + DEFAULT_REMOTE_PORT + ); + exit(1); +} + +static void *gui_thread(void *_g) +{ + gui *g = _g; + gui_loop(g); + return NULL; +} + +static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, + gnb_data *ed) +{ + widget *main_window; + widget *top_container; + widget *line; + widget *w; + logger *l; + view *v; + + main_window = new_toplevel_window(g, 500, 300, "gNB tracer"); + + top_container = new_container(g, VERTICAL); + widget_add_child(g, main_window, top_container, -1); + + line = new_container(g, HORIZONTAL); + widget_add_child(g, top_container, line, -1); + + /* PUCCH/PUSCH IQ data */ + w = new_xy_plot(g, 55, 55, "", 50); + e->pucch_pusch_iq_plot = w; + widget_add_child(g, line, w, -1); + xy_plot_set_range(g, w, -1000, 1000, -1000, 1000); + xy_plot_set_title(g, w, "rxdataF"); + l = new_iqlog_full(h, database, "GNB_PHY_PUCCH_PUSCH_IQ", "rxdataF"); + v = new_view_xy(300*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE); + logger_add_view(l, v); + e->pucch_pusch_iq_logger = l; +} + +int main(int n, char **v) +{ + char *database_filename = NULL; + void *database; + char *ip = DEFAULT_REMOTE_IP; + int port = DEFAULT_REMOTE_PORT; + int *is_on; + int number_of_events; + int i; + event_handler *h; + gnb_data gnb_data; + gui *g; + gnb_gui eg; + + for (i = 1; i < n; i++) { + if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); + if (!strcmp(v[i], "-d")) + { if (i > n-2) usage(); database_filename = v[++i]; continue; } + usage(); + } + + if (database_filename == NULL) { + printf("ERROR: provide a database file (-d)\n"); + exit(1); + } + + database = parse_database(database_filename); + + load_config_file(database_filename); + + number_of_events = number_of_ids(database); + is_on = calloc(number_of_events, sizeof(int)); + if (is_on == NULL) abort(); + + h = new_handler(database); + + on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1); + + gnb_data.database = database; + gnb_data.socket = -1; + gnb_data.is_on = is_on; + gnb_data.nevents = number_of_events; + if (pthread_mutex_init(&gnb_data.lock, NULL)) abort(); + + g = gui_init(); + new_thread(gui_thread, g); + + gnb_main_gui(&eg, g, h, database, &gnb_data); + + OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL }; + +restart: + clear_remote_config(); + if (gnb_data.socket != -1) close(gnb_data.socket); + gnb_data.socket = connect_to(ip, port); + + /* send the first message - activate selected traces */ + is_on_changed(&gnb_data); + + /* read messages */ + while (1) { + event e; + e = get_event(gnb_data.socket, &ebuf, database); + if (e.type == -1) goto restart; + if (pthread_mutex_lock(&gnb_data.lock)) abort(); + handle_event(h, e); + if (pthread_mutex_unlock(&gnb_data.lock)) abort(); + } + + return 0; +} diff --git a/common/utils/T/tracer/logger/iqlog.c b/common/utils/T/tracer/logger/iqlog.c index 168c50e39b..1947de2bca 100644 --- a/common/utils/T/tracer/logger/iqlog.c +++ b/common/utils/T/tracer/logger/iqlog.c @@ -74,6 +74,44 @@ static void _event(void *p, event e) l->common.v[i]->append(l->common.v[i], l->i, l->q, count); } +static void _event_full(void *p, event e) +{ + struct iqlog *l = p; + int i; + void *buffer; + int bsize; + int nsamples; + float *idst, *qdst; + + if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0) + return; + + buffer = e.e[l->buffer_arg].b; + bsize = e.e[l->buffer_arg].bsize; + + nsamples = bsize / 4; + + if (nsamples > l->max_length) { + l->i = realloc(l->i, nsamples * sizeof(float)); + if (l->i == NULL) abort(); + l->q = realloc(l->q, nsamples * sizeof(float)); + if (l->q == NULL) abort(); + l->max_length = nsamples; + } + + idst = l->i; + qdst = l->q; + for (i = 0; i < nsamples; i++) { + *idst = ((int16_t *)buffer)[i * 2]; + *qdst = ((int16_t *)buffer)[i * 2 + 1]; + idst++; + qdst++; + } + + for (i = 0; i < l->common.vsize; i++) + l->common.v[i]->append(l->common.v[i], l->i, l->q, nsamples); +} + logger *new_iqlog(event_handler *h, void *database, char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti, char *buffer_varname) @@ -149,3 +187,43 @@ logger *new_iqlog(event_handler *h, void *database, return ret; } + +logger *new_iqlog_full(event_handler *h, void *database, char *event_name, + char *buffer_varname) +{ + struct iqlog *ret; + int event_id; + database_event_format f; + int i; + + ret = calloc(1, sizeof(struct iqlog)); if (ret == NULL) abort(); + + ret->common.event_name = strdup(event_name); + if (ret->common.event_name == NULL) abort(); + ret->database = database; + + event_id = event_id_from_name(database, event_name); + + ret->common.handler_id = register_handler_function(h, event_id, _event_full, + ret); + + f = get_format(database, event_id); + + /* look for args */ + ret->buffer_arg = -1; + for (i = 0; i < f.count; i++) { + if (!strcmp(f.name[i], buffer_varname)) ret->buffer_arg = i; + } + if (ret->buffer_arg == -1) { + printf("%s:%d: buffer argument '%s' not found in event '%s'\n", + __FILE__, __LINE__, buffer_varname, event_name); + abort(); + } + if (strcmp(f.type[ret->buffer_arg], "buffer") != 0) { + printf("%s:%d: argument '%s' has wrong type (should be 'buffer')\n", + __FILE__, __LINE__, buffer_varname); + abort(); + } + + return ret; +} diff --git a/common/utils/T/tracer/logger/logger.h b/common/utils/T/tracer/logger/logger.h index 7c019b4797..d746161e70 100644 --- a/common/utils/T/tracer/logger/logger.h +++ b/common/utils/T/tracer/logger/logger.h @@ -23,6 +23,8 @@ logger *new_ticklog(void *event_handler, void *database, logger *new_iqlog(void *event_handler, void *database, char *event_name, char *nb_rb, char *N_RB_UL, char *symbols_per_tti, char *buffer_varname); +logger *new_iqlog_full(void *event_handler, void *database, char *event_name, + char *buffer_varname); logger *new_iqdotlog(void *event_handler, void *database, char *event_name, char *I, char *Q); diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 5f07fc00aa..0671aed813 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -32,6 +32,81 @@ #include #include "assertions.h" +#include "nr_common.h" + +// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) +// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) +// Notes: +// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL +// - Frequencies are expressed in KHz +// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster +nr_bandentry_t nr_bandtable[] = { + {1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, + {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, + {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, + {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, + {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, + {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, + {12, 698000, 716000, 729000, 746000, 20, 145800, 100}, + {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, + {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, + {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, + {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, + {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, + {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, + {29, 000, 000, 717000, 728000, 20, 143400, 100}, + {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, + {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, + {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, + {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, + {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, + {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, + {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, + {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, + //{48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, + //{48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, + {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, + {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, + {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, + {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, + {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, + {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, + {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, + {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, + {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, + {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, + {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, + {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, + {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, + {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, + {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, + {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, + {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, + {81, 880000, 915000, 000, 000, 20, 176000, 100}, + {82, 832000, 862000, 000, 000, 20, 166400, 100}, + {83, 703000, 748000, 000, 000, 20, 140600, 100}, + {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, + {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, + {89, 824000, 849000, 000, 000, 20, 342000, 100}, + {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, + {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, + {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, + {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, + {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, + {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, + {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, + {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, + {257,26500020,29500000,26500020,29500000, 1,2054166, 60}, + {257,26500080,29500000,26500080,29500000, 2,2054167, 120}, + {258,24250080,27500000,24250080,27500000, 1,2016667, 60}, + {258,24250080,27500000,24250080,27500000, 2,2016667, 120}, + {260,37000020,40000000,37000020,40000000, 1,2229166, 60}, + {260,37000080,40000000,37000080,40000000, 2,2229167, 120}, + {261,27500040,28350000,27500040,28350000, 1,2070833, 60}, + {261,27500040,28350000,27500040,28350000, 2,2070833, 120} +}; + +const size_t nr_bandtable_size = sizeof(nr_bandtable) / sizeof(nr_bandentry_t); int NRRIV2BW(int locationAndBandwidth,int N_RB) { int tmp = locationAndBandwidth/N_RB; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 5601c0fcbf..6389c2c094 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -36,6 +36,20 @@ #include #include "assertions.h" +typedef struct nr_bandentry_s { + int16_t band; + uint64_t ul_min; + uint64_t ul_max; + uint64_t dl_min; + uint64_t dl_max; + uint64_t step_size; + uint64_t N_OFFs_DL; + uint8_t deltaf_raster; +} nr_bandentry_t; + +extern const size_t nr_bandtable_size; +extern nr_bandentry_t nr_bandtable[]; + int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize); diff --git a/doc/NFAPI_archi.md b/doc/NFAPI_archi.md new file mode 100644 index 0000000000..61c66bd043 --- /dev/null +++ b/doc/NFAPI_archi.md @@ -0,0 +1,132 @@ +# global + +xnf is pnf or vnf + +The xnf starting functions are configure_nfapi_xnf() + +The OAI code that read the configuration parameters call these functions that will create autonomous thread for xnf control part + +These control threads create a SCTP socket by Linux API call (no use of OpenAir internal architecture with SCTP itti thread). + +The main() function of softmodem has to create and start the other threads+loop on event for appropriate work: RF Rx in pnf, NGAP, GTP-U, X2, RLC, PDCP for vnf + +NFAPI has it's own code directly on Linux+Posix, it doesn't reuse any piece of the OpenAir framework: SCTP thread, thread creation and management, ... + +## signaling (P5) xnf main loop + +nfapi_vnf_start() create the SCTP socket, then do event waiting in a infinite loop while(vnf->terminate == 0). It accepts the pnf connections, then process the messages on reception + +nfapi_pnf_start() initiate connection to vnf until it has a link. Then it enter a similar infinite loop in pnf_message_pump() + +After some checks, when a message is obtained, it calls pnf_handle_p5_message() or vnf_handle_p4_p5_message() that have a switch on each p5 message types: the enum nfapi_message_id_e + +Each message type has it's own processing function in the switch, like +``` +case NFAPI_START_RESPONSE: + vnf_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; +``` + +These loops are autonomous in their thread waiting incoming message. + +## P7 xnf main loop + +When the p5 interface receives appropriate message, it starts the p7 interface by launching a thread (see the calls to pthread_create() in nfapi/oai_integration/nfapi_xnf.c) + +The p7 main loops starting is a bit simpler, thanks to UDP non connected protocol. The xnf_dispatch_p7_message() do p7 fragments re-assembly, then +calls xnf_dispatch_p7_message() that have the big switch on message type (as in p5 above description) + +So, we have the logic for UL reception in vnf, and DL reception in pnf + +## P7 UL transmission by PNF + +RF samples are received, and decoding is done by the PNF using control data transmitted by the VNF to the PNF through downlink p7 messages (UL_TTI_req and UL_DCI_req). + +After decoding, results are accumulated into the xNB->UL_INFO structure at the PNF. + +The data in the UL_INFO struct is transmitted through a socket in the form of 'uplink indication functions' from the PNF to the VNF. Each uplink indication message is transmitted from their respective handle functions in NR_UL_indication(). For example, + +``` + +void handle_nr_rach(NR_UL_IND_t *UL_info) { + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->rach_ind.number_of_pdus>0) { + oai_nfapi_nr_rach_indication(&UL_info->rach_ind); //This function calls the routines required for packing + transmission through socket + UL_info->rach_ind.number_of_pdus = 0; + } + } + +``` + +## P7 UL reception at VNF + +Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vnf_p7_start(), the VNF receives and unpacks the uplink indication message received on its socket. Based on the unpacked message, UL_INFO struct on the VNF side gets populated. The NR_UL_indication() function is then called at the VNF, which uses UL_INFO. + +``` + +// have a p7 message + if(FD_ISSET(vnf_p7->socket, &rfds)) + { + vnf_nr_p7_read_dispatch_message(vnf_p7); + + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + } + +``` + +vnf_nr_dispatch_p7_message() is the function that contains the switch on various message headers so that the appropriate unpack function is called. + +## P7 DL Transmission by VNF + +DL messages are scheduled at the VNF, through NR_UL_indication() after processing of UL_INFO. The function performing the scheduling of channels (and consequently p7 messages in nFAPI) is gNB_dlsch_ulsch_scheduler(). + +The function NR_schedule_response calls oai_nfapi_[DL P7 msg]_req(), which contains the routines for packing + transmission of scheduled messages through the socket to the PNF. For example, to send the 'TX_data_req' p7 message + +``` + +if (Sched_INFO->TX_req->Number_of_PDUs > 0) +{ + oai_nfapi_tx_data_req(Sched_INFO->TX_req); +} + +``` + +## P7 DL Reception at PNF + +Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message structures are filled in the PNF, and these are used further down the pipeline for processing. + +While receiving the DL P7 message, we check whether the message was received within a timing window from which it was sent. The duration of the window can be set by the user (set as a parameter for xnf in the p5 messages). A point to note is that the DL information must be received by the PNF within a timing window at least lesser than the duration of slot_ahead variable (timing_window <= slot_ahead * slot_duration). Ideally, it should be received within a duration significantly lesser than slot_ahead so that there is adequate time for PHY processing. + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index d13b193ff9..8d84646e07 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -132,9 +132,9 @@ With the RF simulator (on the same machine): `sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD` -## sa setup with OAI +## SA setup with OAI -The sa flag is used to run gNB in standalone mode. Currently OAI in NR standalone mode transmits and receives SIB1. +The sa flag is used to run gNB in standalone mode. Currently OAI in NR standalone mode transmits and receives SIB1 and triggers the RA procedure for initial access. In order to run gNB in standalone mode, the following flag is needed at gNB: @@ -147,8 +147,9 @@ At the gNB the --sa flag does the following - it encodes the RRCConfiguration and the RBconfig message and stores them in the binary files rbconfig.raw and reconfig.raw - the RRC encodes SIB1 according the configuration file and transmits it through PDSCH -At the UE the --sa flag will -- read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them. +At the UE the --sa flag will: +- Read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them +- After the successful decoding of a SIB1 at RRC, the UE will start the 5G NR Initial Access Procedure by triggering the RA procedure. From the `cmake_targets/ran_build/build` folder: @@ -168,7 +169,7 @@ With the RF simulator (on the same machine): ## IF setup with OAI -The -C and -CO flags can be used together at UE side to set custom downlink and uplink FR1 intermediate frequencies for the IF equipment. +The -C and --CO flags can be used together at UE side to set custom downlink and uplink FR1 arbitrary frequencies for the IF equipment. In order to run this setup, the following flags are needed at the UE side: @@ -182,9 +183,11 @@ and the following parameters must be configured in the RUs section of the gNB co `if_offset` -### Run OAI with custom DL/UL intermediate frequencies +The values must be given in Hz. -The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 at gNB side. +### Run OAI with custom DL/UL arbitrary frequencies + +The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 (FDD) at gNB side. From the `cmake_targets/ran_build/build` folder: diff --git a/docker/Dockerfile.eNB.rhel8.2 b/docker/Dockerfile.eNB.rhel8.2 index 5fcd5a7b9f..aa8b9aa228 100644 --- a/docker/Dockerfile.eNB.rhel8.2 +++ b/docker/Dockerfile.eNB.rhel8.2 @@ -27,14 +27,15 @@ FROM localhost/ran-build:latest AS enb-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --eNB --ninja -w USRP + ./build_oai --eNB --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-softmodem.Rel15 diff --git a/docker/Dockerfile.eNB.ubuntu18 b/docker/Dockerfile.eNB.ubuntu18 index cdfb37ebfc..95d7194c31 100644 --- a/docker/Dockerfile.eNB.ubuntu18 +++ b/docker/Dockerfile.eNB.ubuntu18 @@ -27,14 +27,15 @@ FROM ran-build:latest AS enb-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --eNB --ninja -w USRP + ./build_oai --eNB --ninja -w USRP --verbose-ci RUN apt-get install -y python3-pip && \ pip3 install --ignore-installed pyyaml && \ diff --git a/docker/Dockerfile.gNB.rhel8.2 b/docker/Dockerfile.gNB.rhel8.2 index fb9ade927f..6969c691fd 100644 --- a/docker/Dockerfile.gNB.rhel8.2 +++ b/docker/Dockerfile.gNB.rhel8.2 @@ -27,14 +27,15 @@ FROM localhost/ran-build:latest AS gnb-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --gNB --ninja -w USRP + ./build_oai --gNB --ninja -w USRP --verbose-ci #debug #RUN ldconfig -v diff --git a/docker/Dockerfile.gNB.ubuntu18 b/docker/Dockerfile.gNB.ubuntu18 index d43ad4709d..276d6989c4 100644 --- a/docker/Dockerfile.gNB.ubuntu18 +++ b/docker/Dockerfile.gNB.ubuntu18 @@ -27,14 +27,15 @@ FROM ran-build:latest AS gnb-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --gNB --ninja -w USRP + ./build_oai --gNB --ninja -w USRP --verbose-ci #debug RUN ldconfig -v diff --git a/docker/Dockerfile.lteUE.rhel8.2 b/docker/Dockerfile.lteUE.rhel8.2 index 0a853dcd6b..e22343d63c 100644 --- a/docker/Dockerfile.lteUE.rhel8.2 +++ b/docker/Dockerfile.lteUE.rhel8.2 @@ -27,15 +27,15 @@ FROM localhost/ran-build:latest AS lte-ue-build - +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --UE --ninja -w USRP + ./build_oai --UE --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-uesoftmodem.Rel15 diff --git a/docker/Dockerfile.lteUE.ubuntu18 b/docker/Dockerfile.lteUE.ubuntu18 index 8793cc54f7..6af2e61991 100644 --- a/docker/Dockerfile.lteUE.ubuntu18 +++ b/docker/Dockerfile.lteUE.ubuntu18 @@ -27,14 +27,15 @@ FROM ran-build:latest AS lte-ue-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --UE --ninja -w USRP + ./build_oai --UE --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2 index f9f3f8e4bf..01988fd6ff 100644 --- a/docker/Dockerfile.nrUE.rhel8.2 +++ b/docker/Dockerfile.nrUE.rhel8.2 @@ -27,14 +27,15 @@ FROM localhost/ran-build:latest AS nr-ue-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --nrUE --ninja -w USRP + ./build_oai --nrUE --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v diff --git a/docker/Dockerfile.nrUE.ubuntu18 b/docker/Dockerfile.nrUE.ubuntu18 index 5450194f35..c96bcf80ef 100644 --- a/docker/Dockerfile.nrUE.ubuntu18 +++ b/docker/Dockerfile.nrUE.ubuntu18 @@ -27,14 +27,15 @@ FROM ran-build:latest AS nr-ue-build +RUN rm -Rf /oai-ran WORKDIR /oai-ran +COPY . . #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ - rm -Rf log && \ mkdir -p log && \ - ./build_oai --nrUE --ninja -w USRP + ./build_oai --nrUE --ninja -w USRP --verbose-ci # debug #RUN ldconfig -v diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 2f7944e313..410c41d9b1 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -81,10 +81,11 @@ #include "s1ap_eNB.h" #include "SIMULATION/ETH_TRANSPORT/proto.h" - +#include #include "T.h" #include "nfapi/oai_integration/vendor_ext.h" +#include //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 @@ -92,17 +93,6 @@ // extern openair0_device openair0; -extern volatile int start_gNB; -extern volatile int start_UE; -extern volatile int oai_exit; - -extern openair0_config_t openair0_cfg[MAX_CARDS]; - -extern int transmission_mode; - -extern uint16_t sf_ahead; -extern uint16_t sl_ahead; - //pthread_t main_gNB_thread; time_stats_t softmodem_stats_mt; // main thread @@ -111,40 +101,43 @@ time_stats_t softmodem_stats_rxtx_sf; // total tx time time_stats_t nfapi_meas; // total tx time time_stats_t softmodem_stats_rx_sf; // total rx time -/* mutex, cond and variable to serialize phy proc TX calls - * (this mechanism may be relaxed in the future for better - * performances) - */ -static struct { - pthread_mutex_t mutex_phy_proc_tx; - pthread_cond_t cond_phy_proc_tx; - volatile uint8_t phy_proc_CC_id; -} sync_phy_proc; -extern double cpuf; - -void init_gNB(int,int); -void stop_gNB(int nb_inst); - -int wakeup_txfh(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, int frame_tx, int slot_tx, uint64_t timestamp_tx); -int wakeup_tx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, uint64_t timestamp_tx); #include "executables/thread-common.h" -//extern PARALLEL_CONF_t get_thread_parallel_conf(void); -//extern WORKER_CONF_t get_thread_worker_conf(void); -void wakeup_prach_gNB(PHY_VARS_gNB *gNB, RU_t *ru, int frame, int subframe); - -extern uint8_t nfapi_mode; -extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); -extern void oai_slot_ind(uint16_t sfn, uint16_t slot); -extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset); - //#define TICK_TO_US(ts) (ts.diff) #define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials) -static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_tx, int slot_tx, char *thread_name) { +void tx_func(void *param) { + + processingData_L1_t *info = (processingData_L1_t *) param; + PHY_VARS_gNB *gNB = info->gNB; + int frame_tx = info->frame_tx; + int slot_tx = info->slot_tx; + + phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); + + // start FH TX processing + notifiedFIFO_elt_t *res; + res = pullTpool(gNB->resp_RU_tx, gNB->threadPool); + processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res); + syncMsg->frame_tx = frame_tx; + syncMsg->slot_tx = slot_tx; + syncMsg->timestamp_tx = info->timestamp_tx; + syncMsg->ru = gNB->RU_list[0]; + res->key = slot_tx; + pushTpool(gNB->threadPool, res); +} + +void rx_func(void *param) { + //printf("inside rx func. \n"); + processingData_L1_t *info = (processingData_L1_t *) param; + PHY_VARS_gNB *gNB = info->gNB; + int frame_rx = info->frame_rx; + int slot_rx = info->slot_rx; + int frame_tx = info->frame_tx; + int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; @@ -235,22 +228,18 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t rnti_to_remove_count = 0; if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); - /* - // if this is IF5 or 3GPP_gNB - if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) { - wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx); - } - */ // Call the scheduler - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = frame_rx; - gNB->UL_INFO.slot = slot_rx; - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); - + if(NFAPI_MODE == NFAPI_MONOLITHIC) + { + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = frame_rx; + gNB->UL_INFO.slot = slot_rx; + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + } // RX processing int tx_slot_type; int rx_slot_type; if(NFAPI_MODE != NFAPI_MONOLITHIC) { //slot selection routines not working properly in nfapi, so temporarily hardcoding @@ -298,23 +287,24 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx); } - if (oai_exit) return(-1); - - // ***************************************** - // TX processing for subframe n+sf_ahead - // run PHY TX procedures the one after the other for all CCs to avoid race conditions - // (may be relaxed in the future for performance reasons) - // ***************************************** - - if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { - - if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) { - phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); - } - } - stop_meas( &softmodem_stats_rxtx_sf ); LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx); + + notifiedFIFO_elt_t *res; + + if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { + res = pullTpool(gNB->resp_L1_tx, gNB->threadPool); + processingData_L1_t *syncMsg = (processingData_L1_t *)NotifiedFifoData(res); + syncMsg->gNB = gNB; + syncMsg->frame_rx = frame_rx; + syncMsg->slot_rx = slot_rx; + syncMsg->frame_tx = frame_tx; + syncMsg->slot_tx = slot_tx; + syncMsg->timestamp_tx = info->timestamp_tx; + res->key = slot_tx; + pushTpool(gNB->threadPool, res); + } + #if 0 LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ", softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now, @@ -354,477 +344,7 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t TICK_TO_US(gNB->ulsch_tc_intl2_stats) ); #endif - return(0); } - -static void *gNB_L1_thread_tx(void *param) { - PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; - gNB_L1_proc_t *gNB_proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB_proc->L1_proc_tx; - //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; - char thread_name[100]; - - sprintf(thread_name,"gNB_L1_thread_tx\n"); - - while (!oai_exit) { - if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 ); - - if (oai_exit) break; - - // ***************************************** - // TX processing for subframe n+4 - // run PHY TX procedures the one after the other for all CCs to avoid race conditions - // (may be relaxed in the future for performance reasons) - // ***************************************** - int frame_tx = L1_proc_tx->frame_tx; - int slot_tx = L1_proc_tx->slot_tx; - uint64_t timestamp_tx = L1_proc_tx->timestamp_tx; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx); - phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 1 ); - pthread_mutex_lock( &L1_proc_tx->mutex ); - L1_proc_tx->instance_cnt = -1; - - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc_tx->cond) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - } - pthread_mutex_unlock(&L1_proc_tx->mutex); - - wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 ); - } - - return 0; -} - -/*! - * \brief The RX UE-specific and TX thread of gNB. - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ - -static void *gNB_L1_thread( void *param ) { - static int gNB_thread_rxtx_status; - PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; - gNB_L1_proc_t *gNB_proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc; - //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; - char thread_name[100]; - // set default return value - // set default return value - gNB_thread_rxtx_status = 0; - - sprintf(thread_name,"gNB_L1_thread"); - - - while (!oai_exit) { - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); - int frame_rx = L1_proc->frame_rx; - int slot_rx; - if (NFAPI_MODE == NFAPI_MODE_PNF) - slot_rx = (L1_proc->slot_rx) + 1; - else - slot_rx = L1_proc->slot_rx; - int frame_tx = L1_proc->frame_tx; - int slot_tx = L1_proc->slot_tx; - uint64_t timestamp_tx = L1_proc->timestamp_tx; - if(NFAPI_MODE==NFAPI_MODE_VNF) - if (gNB->CC_id==0) { - int next_slot; - next_slot = (slot_rx + 1) % 20; - if (rxtx(gNB,frame_rx,next_slot,frame_tx,next_slot,thread_name) < 0) break; - } - if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); - - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_GNB,frame_rx); - - if (oai_exit) break; - - if (gNB->CC_id==0) { - if (rxtx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,thread_name) < 0) break; - } - - - if (release_thread(&L1_proc->mutex,&L1_proc->instance_cnt,thread_name)<0) break; - - if (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(gNB,frame_rx,slot_rx,frame_tx,slot_tx,timestamp_tx); - else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(gNB,L1_proc,frame_tx,slot_tx,timestamp_tx); - } // while !oai_exit - - LOG_D(PHY, " *** Exiting gNB thread RXn_TXnp4\n"); - gNB_thread_rxtx_status = 0; - return &gNB_thread_rxtx_status; -} - - -#if 0 -// Wait for gNB application initialization to be complete (gNB registration to MME) -static void wait_system_ready (char *message, volatile int *start_flag) { - static char *indicator[] = {". ", ".. ", "... ", ".... ", ".....", - " ....", " ...", " ..", " .", " " - }; - int i = 0; - - while ((!oai_exit) && (*start_flag == 0)) { - LOG_N(EMU, message, indicator[i]); - fflush(stdout); - i = (i + 1) % (sizeof(indicator) / sizeof(indicator[0])); - usleep(200000); - } - - LOG_D(EMU,"\n"); -} -#endif - - - - - -void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru) { - gNB_L1_proc_t *proc = &gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc = &proc->L1_proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *ru_proc=&ru->proc; - proc->frame_rx = frame_rx; - proc->slot_rx = slot_rx; - sl_ahead = sf_ahead*fp->slots_per_subframe; - - if (!oai_exit) { - T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->slot_rx)); - L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); - L1_proc->frame_rx = ru_proc->frame_rx; - L1_proc->slot_rx = ru_proc->tti_rx; - L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - - if (rxtx(gNB,L1_proc->frame_rx,L1_proc->slot_rx,L1_proc->frame_tx,L1_proc->slot_tx,string) < 0) LOG_E(PHY,"gNB %d CC_id %d failed during execution\n",gNB->Mod_id,gNB->CC_id); - - ru_proc->timestamp_tx = L1_proc->timestamp_tx; - ru_proc->tti_tx = L1_proc->slot_tx; - ru_proc->frame_tx = L1_proc->frame_tx; - } -} - -int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) { - - RU_t *ru; - RU_proc_t *ru_proc; - - int waitret = 0, ret = 0, time_ns = 1000*1000; - struct timespec now, abstime; - // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time - // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1); - time_ns = time_ns/gNB->frame_parms.slots_per_subframe; - AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - while (proc->instance_cnt_RUs < 0) { - clock_gettime(CLOCK_REALTIME, &now); - abstime.tv_sec = now.tv_sec; - abstime.tv_nsec = now.tv_nsec + time_ns; - - if (abstime.tv_nsec >= 1000*1000*1000) { - abstime.tv_nsec -= 1000*1000*1000; - abstime.tv_sec += 1; - } - if((waitret = pthread_cond_timedwait(&proc->cond_RUs,&proc->mutex_RUs_tx,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again - } - proc->instance_cnt_RUs = -1; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0); - - if (waitret == ETIMEDOUT) { - LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); - - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); - - return(-1); - } - - for(int i=0; inum_RU; i++) - { - ru = gNB->RU_list[i]; - ru_proc = &ru->proc; - - - if (ru_proc->instance_cnt_gNBs == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1); - LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->tti_tx, proc->frame_rx, proc->slot_rx); - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0); - return(-1); - } - AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret); - - ru_proc->instance_cnt_gNBs = 0; - ru_proc->timestamp_tx = timestamp_tx; - ru_proc->tti_tx = slot_tx; - ru_proc->frame_tx = frame_tx; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs); - - LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0, - "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); - AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret); - - } - return(0); -} - -int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) { - - - gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx; - - int ret; - - - AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); - - - while(L1_proc_tx->instance_cnt == 0) { - pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex); - } - - L1_proc_tx->instance_cnt = 0; - - - L1_proc_tx->slot_rx = slot_rx; - L1_proc_tx->frame_rx = frame_rx; - L1_proc_tx->slot_tx = slot_tx; - L1_proc_tx->frame_tx = frame_tx; - L1_proc_tx->timestamp_tx = timestamp_tx; - - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0); - // the thread can now be woken up - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n"); - - AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); - - return(0); -} - -int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { - gNB_L1_proc_t *proc=&gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc=&proc->L1_proc; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - RU_proc_t *ru_proc=&ru->proc; - int ret; - int i; - struct timespec abstime; - int time_ns = 50000; - int wait_timer = 0; - bool do_last_check = 1; - - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); - for (i=0; inum_RU; i++) { - if (ru == gNB->RU_list[i]) { - if ((proc->RU_mask&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); - proc->RU_mask |= (1<RU_mask != (1<num_RU)-1) { // not all RUs have provided their information so return - LOG_E(PHY,"Not all RUs have provided their info\n"); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret); - return(0); - } - else { // all RUs have provided their information so continue on and wakeup gNB processing - proc->RU_mask = 0; - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret); - } - - // wake up TX for subframe n+sf_ahead - // lock the TX mutex and make sure the thread is ready - while (wait_timer < 200) { - clock_gettime(CLOCK_REALTIME, &abstime); - abstime.tv_nsec = abstime.tv_nsec + time_ns; - - if (abstime.tv_nsec >= 1000*1000*1000) { - abstime.tv_nsec -= 1000*1000*1000; - abstime.tv_sec += 1; - } - - AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret); - - if (L1_proc->instance_cnt == 0) { // L1_thread is busy so wait for a bit - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); - wait_timer += 50; - usleep(50); - } - else { - do_last_check = 0; - break; - } - } - if (do_last_check) { - AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret); - if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); - LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); - return (-1); - } - } - - ++L1_proc->instance_cnt; - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired - // transmitted timestamp of the next TX slot (first). - - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, - // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti, - // and proc->slot_tx = proc->slot_rx+sf_ahead - L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); - L1_proc->frame_rx = ru_proc->frame_rx; - L1_proc->slot_rx = ru_proc->tti_rx; - L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->slot_tx = (L1_proc->slot_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - - LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sf_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sf_ahead); - - pthread_mutex_unlock( &L1_proc->mutex ); - - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc->cond) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - - return(0); -} -/* -void wakeup_prach_gNB(PHY_VARS_gNB *gNB,RU_t *ru,int frame,int subframe) { - - gNB_L1_proc_t *proc = &gNB->proc; - LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms; - int i; - - if (ru!=NULL) { - pthread_mutex_lock(&proc->mutex_RU_PRACH); - for (i=0;inum_RU;i++) { - if (ru == gNB->RU_list[i]) { - LOG_D(PHY,"frame %d, subframe %d: RU %d for gNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,gNB->Mod_id,proc->RU_mask_prach,gNB->num_RU); - if ((proc->RU_mask_prach&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information (PRACH) from RU %d (num_RU %d, mask %x) has not been served yet!\n", - gNB->Mod_id,frame,subframe,ru->idx,gNB->num_RU,proc->RU_mask_prach); - proc->RU_mask_prach |= (1<RU_mask_prach != (1<num_RU)-1) { // not all RUs have provided their information so return - pthread_mutex_unlock(&proc->mutex_RU_PRACH); - return; - } - else { // all RUs have provided their information so continue on and wakeup gNB processing - proc->RU_mask_prach = 0; - pthread_mutex_unlock(&proc->mutex_RU_PRACH); - } - } - - // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - LOG_D(PHY,"Triggering prach processing, frame %d, subframe %d\n",frame,subframe); - if (proc->instance_cnt_prach == 0) { - LOG_W(PHY,"[gNB] Frame %d Subframe %d, dropping PRACH\n", frame,subframe); - return; - } - - // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach); - exit_fun( "error locking mutex_prach" ); - return; - } - - ++proc->instance_cnt_prach; - // set timing for prach thread - proc->frame_prach = frame; - proc->subframe_prach = subframe; - - // the thread can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB PRACH thread %d\n", proc->thread_index); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - - pthread_mutex_unlock( &proc->mutex_prach ); - } - -}*/ - -/*! - * \brief The prach receive thread of gNB. - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -/* -static void* gNB_thread_prach( void* param ) { - static int gNB_thread_prach_status; - - - PHY_VARS_gNB *gNB= (PHY_VARS_gNB *)param; - gNB_L1_proc_t *proc = &gNB->proc; - - // set default return value - gNB_thread_prach_status = 0; - - - - while (!oai_exit) { - - if (oai_exit) break; - - - if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break; - - LOG_D(PHY,"Running gNB prach procedures\n"); - prach_procedures(gNB ,0); - - if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"gNB_prach_thread") < 0) break; - } - - LOG_I(PHY, "Exiting gNB thread PRACH\n"); - - gNB_thread_prach_status = 0; - return &gNB_thread_prach_status; -} -*/ - -extern void init_td_thread(PHY_VARS_gNB *); -extern void init_te_thread(PHY_VARS_gNB *); - static void *process_stats_thread(void *param) { PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; @@ -845,71 +365,13 @@ static void *process_stats_thread(void *param) { return(NULL); } - -void init_gNB_proc(int inst) { - int i=0; - int CC_id = 0; +void init_gNB_Tpool(int inst) { PHY_VARS_gNB *gNB; - gNB_L1_proc_t *proc; - gNB_L1_rxtx_proc_t *L1_proc,*L1_proc_tx; -// LOG_I(PHY,"%s(inst:%d) RC.nb_nr_CC[inst]:%d \n",__FUNCTION__,inst,RC.nb_nr_CC[inst]); gNB = RC.gNB[inst]; - LOG_I(PHY,"Initializing gNB processes instance:%d CC_id %d \n",inst,CC_id); - - proc = &gNB->proc; - L1_proc = &proc->L1_proc; - L1_proc_tx = &proc->L1_proc_tx; - L1_proc->instance_cnt = -1; - L1_proc_tx->instance_cnt = -1; - L1_proc->instance_cnt_RUs = 0; - L1_proc_tx->instance_cnt_RUs = 0; - proc->instance_cnt_prach = -1; - proc->instance_cnt_asynch_rxtx = -1; - proc->CC_id = CC_id; - proc->first_rx =1; - proc->first_tx =1; - proc->RU_mask =0; - proc->RU_mask_tx = (1<num_RU)-1; - proc->RU_mask_prach =0; - pthread_mutex_init( &gNB->UL_INFO_mutex, NULL); - pthread_mutex_init( &L1_proc->mutex, NULL); - pthread_mutex_init( &L1_proc_tx->mutex, NULL); - pthread_cond_init( &L1_proc->cond, NULL); - pthread_cond_init( &L1_proc_tx->cond, NULL); - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); - pthread_mutex_init( &proc->mutex_RU,NULL); - pthread_mutex_init( &proc->mutex_RU_tx,NULL); - pthread_mutex_init( &proc->mutex_RU_PRACH,NULL); - pthread_cond_init( &proc->cond_prach, NULL); - pthread_cond_init( &proc->cond_asynch_rxtx, NULL); - LOG_I(PHY,"gNB->single_thread_flag:%d\n", gNB->single_thread_flag); - - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - threadCreate( &L1_proc->pthread, gNB_L1_thread, gNB, "L1_proc", -1, OAI_PRIORITY_RT ); - threadCreate( &L1_proc_tx->pthread, gNB_L1_thread_tx, gNB,"L1_proc_tx", -1, OAI_PRIORITY_RT); - } - - if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW); - //pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB ); - char name[16]; - - if (gNB->single_thread_flag==0) { - snprintf( name, sizeof(name), "L1 %d", i ); - pthread_setname_np( L1_proc->pthread, name ); - snprintf( name, sizeof(name), "L1TX %d", i ); - pthread_setname_np( L1_proc_tx->pthread, name ); - } - - AssertFatal(proc->instance_cnt_prach == -1,"instance_cnt_prach = %d\n",proc->instance_cnt_prach); - - /* setup PHY proc TX sync mechanism */ - pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL); - pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL); - sync_phy_proc.phy_proc_CC_id = 0; + gNB_L1_proc_t *proc = &gNB->proc; + // ULSCH decoding threadpool gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); - gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); int numCPU = sysconf(_SC_NPROCESSORS_ONLN); int threadCnt = min(numCPU, gNB->pusch_proc_threads); char ul_pool[80]; @@ -920,70 +382,40 @@ void init_gNB_proc(int inst) { s_offset += 3; } initTpool(ul_pool, gNB->threadPool, false); + // ULSCH decoder result FIFO + gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); initNotifiedFIFO(gNB->respDecode); -} + // L1 RX result FIFO + gNB->resp_L1 = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_L1); + + // L1 TX result FIFO + gNB->resp_L1_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_L1_tx); + + // RU TX result FIFO + gNB->resp_RU_tx = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(gNB->resp_RU_tx); + + // Stats measurement thread + if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW); +} /*! * \brief Terminate gNB TX and RX threads. */ void kill_gNB_proc(int inst) { - int *status; PHY_VARS_gNB *gNB; - gNB_L1_proc_t *proc; - gNB_L1_rxtx_proc_t *L1_proc, *L1_proc_tx; gNB=RC.gNB[inst]; - proc = &gNB->proc; - L1_proc = &proc->L1_proc; - L1_proc_tx = &proc->L1_proc_tx; - LOG_I(PHY, "Killing TX inst %d\n",inst ); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - pthread_mutex_lock(&L1_proc->mutex); - L1_proc->instance_cnt = 0; - pthread_cond_signal(&L1_proc->cond); - pthread_mutex_unlock(&L1_proc->mutex); - pthread_mutex_lock(&L1_proc_tx->mutex); - L1_proc_tx->instance_cnt = 0; - pthread_cond_signal(&L1_proc_tx->cond); - pthread_mutex_unlock(&L1_proc_tx->mutex); - } - - proc->instance_cnt_prach = 0; - pthread_cond_signal( &proc->cond_prach ); - pthread_cond_signal( &proc->cond_asynch_rxtx ); - pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); - // LOG_D(PHY, "joining pthread_prach\n"); - // pthread_join( proc->pthread_prach, (void**)&status ); - LOG_I(PHY, "Destroying prach mutex/cond\n"); - pthread_mutex_destroy( &proc->mutex_prach ); - pthread_cond_destroy( &proc->cond_prach ); LOG_I(PHY, "Destroying UL_INFO mutex\n"); pthread_mutex_destroy(&gNB->UL_INFO_mutex); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) { - LOG_I(PHY, "Joining L1_proc mutex/cond\n"); - pthread_join( L1_proc->pthread, (void **)&status ); - LOG_I(PHY, "Joining L1_proc_tx mutex/cond\n"); - pthread_join( L1_proc_tx->pthread, (void **)&status ); - } - - LOG_I(PHY, "Destroying L1_proc mutex/cond\n"); - pthread_mutex_destroy( &L1_proc->mutex ); - pthread_cond_destroy( &L1_proc->cond ); - LOG_I(PHY, "Destroying L1_proc_tx mutex/cond\n"); - pthread_mutex_destroy( &L1_proc_tx->mutex ); - pthread_cond_destroy( &L1_proc_tx->cond ); - pthread_mutex_destroy( &proc->mutex_RU ); - pthread_mutex_destroy( &proc->mutex_RU_tx ); - } - - - void reset_opp_meas(void) { int sfn; reset_meas(&softmodem_stats_mt); @@ -1051,15 +483,9 @@ printf("after %p\n", gNB->common_vars.rxdataF[aa]); * (not tested in other modes). */ //init_precoding_weights(RC.gNB[inst]); - init_gNB_proc(inst); + init_gNB_Tpool(inst); } - for (ru_id=0; ru_idnr_wakeup_rxtx = wakeup_rxtx; - // RC.ru[ru_id]->wakeup_prach_eNB = wakeup_prach_gNB; - RC.ru[ru_id]->gNB_top = gNB_top; - } } void init_gNB(int single_thread_flag,int wait_for_sync) { diff --git a/executables/nr-ru.c b/executables/nr-ru.c index d0bc1a3e0e..1e8cae3adc 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -790,259 +790,6 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { } } - - -/*! - * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU. - * This handles the RX FH for an asynchronous RRU/UE - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_asynch_rxtx( void *param ) { - static int ru_thread_asynch_rxtx_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - int slot=0, frame=0; - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - wait_sync("ru_thread_asynch_rxtx"); - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for devices (ru_thread_asynch_rx)\n"); - wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); - printf( "devices ok (ru_thread_asynch_rx)\n"); - - while (!oai_exit) { - - if (slot==ru->nr_frame_parms->slots_per_frame) { - slot=0; - frame++; - frame&=1023; - } else { - slot++; - } - - LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); - - // asynchronous receive from north (RRU IF4/IF5) - if (ru->fh_north_asynch_in) { - if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0) - ru->fh_north_asynch_in(ru,&frame,&slot); - } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n"); - } - - ru_thread_asynch_rxtx_status=0; - return(&ru_thread_asynch_rxtx_status); -} - - - - -/*! - * \brief The prach receive thread of RU. - * \param param is a \ref RU_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_prach( void *param ) { - static int ru_thread_prach_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = (RU_proc_t *)&ru->proc; - // set default return value - ru_thread_prach_status = 0; - - while (RC.ru_mask>0) { - usleep(1e6); - LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__); - } - - LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__); - - while (!oai_exit) { - - - if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - - /*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); - - if (ru->gNB_list[0]){ - prach_procedures( - ru->gNB_list[0],0 - ); - } - else { - rx_prach(NULL, - ru, - NULL, - NULL, - NULL, - proc->frame_prach, - 0,0 - ); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ - if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - } - - LOG_I(PHY, "Exiting RU thread PRACH\n"); - ru_thread_prach_status = 0; - return &ru_thread_prach_status; -} - - -int wakeup_synch(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - // wake up synch thread - // lock the synch mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch ); - exit_fun( "error locking mutex_synch" ); - return(-1); - } - - ++ru->proc.instance_cnt_synch; - - // the thread can now be woken up - if (pthread_cond_signal(&ru->proc.cond_synch) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - - pthread_mutex_unlock( &ru->proc.mutex_synch ); - return(0); -} - -void do_ru_synch(RU_t *ru) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int i; - void *rxp[2],*rxp2[2]; - int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32))); - int rxs; - int ic; - - // initialize the synchronization buffer to the common_vars.rxdata - for (int i=0; inb_rx; i++) - rxp[i] = &ru->common.rxdata[i][0]; - - double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0]; - double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0]; - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i]; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); - - while ((ru->in_synch ==0)&&(!oai_exit)) { - // read in frame - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - fp->samples_per_subframe*10, - ru->nb_rx); - - if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs); - - // wakeup synchronization processing thread - wakeup_synch(ru); - ic=0; - - while ((ic>=0)&&(!oai_exit)) { - // continuously read in frames, 1ms at a time, - // until we are done with the synchronization procedure - for (i=0; inb_rx; i++) - rxp2[i] = (void *)&dummy_rx[i][0]; - - for (i=0; i<10; i++) - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp2, - fp->samples_per_subframe, - ru->nb_rx); - - pthread_mutex_lock(&ru->proc.mutex_synch); - ic = ru->proc.instance_cnt_synch; - pthread_mutex_unlock(&ru->proc.mutex_synch); - } // ic>=0 - } // in_synch==0 - - // read in rx_offset samples - LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset); - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - ru->rx_offset, - ru->nb_rx); - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); -} - - - -void wakeup_gNB_L1s(RU_t *ru) { - int i; - PHY_VARS_gNB **gNB_list = ru->gNB_list; - LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top); - - if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { - // call gNB function directly - char string[20]; - sprintf(string,"Incoming RU %u",ru->idx); - LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx); - ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru); - } else { - LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB); - - for (i=0; inum_gNB; i++) { - LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx); - - if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) { - LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx); - } - } - } -} - -int wakeup_prach_ru(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } - - if (ru->proc.instance_cnt_prach==-1) { - ++ru->proc.instance_cnt_prach; - ru->proc.frame_prach = ru->proc.frame_rx; - ru->proc.subframe_prach = ru->proc.tti_rx; - - // DJP - think prach_procedures() is looking at gNB frame_prach - if (ru->gNB_list[0]) { - ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx; - ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx; - } - - LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx); - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); - } else LOG_W(PHY,"RU prach thread busy, skipping\n"); - - pthread_mutex_unlock( &ru->proc.mutex_prach ); - return(0); -} - // this is for RU with local RF unit void fill_rf_config(RU_t *ru, char *rf_config_file) { int i; @@ -1052,58 +799,21 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { int mu = config->ssb_config.scs_common.value; int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - if (mu == NR_MU_0) { //or if LTE - if(N_RB == 100) { - if (fp->threequarter_fs) { - cfg->sample_rate=23.04e6; - cfg->samples_per_frame = 230400; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } else { - cfg->sample_rate=30.72e6; - cfg->samples_per_frame = 307200; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - } else if(N_RB == 50) { - cfg->sample_rate=15.36e6; - cfg->samples_per_frame = 153600; - cfg->tx_bw = 5e6; - cfg->rx_bw = 5e6; - } else if (N_RB == 25) { - cfg->sample_rate=7.68e6; - cfg->samples_per_frame = 76800; - cfg->tx_bw = 2.5e6; - cfg->rx_bw = 2.5e6; - } else if (N_RB == 6) { - cfg->sample_rate=1.92e6; - cfg->samples_per_frame = 19200; - cfg->tx_bw = 1.5e6; - cfg->rx_bw = 1.5e6; - } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB); - } else if (mu == NR_MU_1) { - if(N_RB == 273) { - if (fp->threequarter_fs) { - AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } - } else if(N_RB == 217) { + if (mu == NR_MU_0) { + switch(N_RB) { + case 270: if (fp->threequarter_fs) { cfg->sample_rate=92.16e6; cfg->samples_per_frame = 921600; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; } - } else if(N_RB == 106) { + case 216: if (fp->threequarter_fs) { cfg->sample_rate=46.08e6; cfg->samples_per_frame = 460800; @@ -1116,20 +826,154 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { cfg->tx_bw = 40e6; cfg->rx_bw = 40e6; } - } else { + break; + case 106: + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + break; + case 52: + if (fp->threequarter_fs) { + cfg->sample_rate=11.52e6; + cfg->samples_per_frame = 115200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + else { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + case 25: + if (fp->threequarter_fs) { + cfg->sample_rate=5.76e6; + cfg->samples_per_frame = 57600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } + else { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } + break; + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); + } + } else if (mu == NR_MU_1) { + switch(N_RB) { + case 273: + if (fp->threequarter_fs) { + cfg->sample_rate=184.32e6; + cfg->samples_per_frame = 1843200; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + break; + case 217: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } else { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 80e6; + cfg->rx_bw = 80e6; + } + break; + case 106: + if (fp->threequarter_fs) { + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } + break; + case 51: + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } + break; + case 24: + if (fp->threequarter_fs) { + cfg->sample_rate=11.52e6; + cfg->samples_per_frame = 115200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + else { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + break; + default: AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else if (mu == NR_MU_3) { - if (N_RB == 66) { - cfg->sample_rate = 122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } else if(N_RB == 32) { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; + switch(N_RB) { + case 66: + if (fp->threequarter_fs) { + cfg->sample_rate=184.32e6; + cfg->samples_per_frame = 1843200; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } else { + cfg->sample_rate = 122.88e6; + cfg->samples_per_frame = 1228800; + cfg->tx_bw = 100e6; + cfg->rx_bw = 100e6; + } + break; + case 32: + if (fp->threequarter_fs) { + cfg->sample_rate=92.16e6; + cfg->samples_per_frame = 921600; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } else { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 50e6; + cfg->rx_bw = 50e6; + } + break; + default: + AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); } } else { AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); @@ -1176,60 +1020,52 @@ int setup_RU_buffers(RU_t *ru) { int i,j; int card,ant; //uint16_t N_TA_offset = 0; - NR_DL_FRAME_PARMS *frame_parms; + NR_DL_FRAME_PARMS *fp; nfapi_nr_config_request_scf_t *config = &ru->config; if (ru) { - frame_parms = ru->nr_frame_parms; - printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + fp = ru->nr_frame_parms; + printf("setup_RU_buffers: frame_parms = %p\n",fp); } else { printf("ru pointer is NULL\n"); return(-1); } + int mu = config->ssb_config.scs_common.value; int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - if (config->cell_config.frame_duplex_type.value == TDD) { int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 double factor=1; - switch (mu) { - case 0: //15 kHz scs - AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n"); - if (N_RB <= 25) factor = .25; // 7.68 Ms/s - else if (N_RB <=50) factor = .5; // 15.36 Ms/s - else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s - else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s - else AssertFatal(1==0,"Too many PRBS for mu=0\n"); - break; - case 1: //30 kHz sc - AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n"); - if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s - else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s - break; - case 2: //60 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - break; - case 3: //120 kHz scs - AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n"); - break; - case 4: //240 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s - else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s - else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); - break; - - if (N_RB == 100) ru->N_TA_offset = 624; - else if (N_RB == 50) ru->N_TA_offset = 624/2; - else if (N_RB == 25) ru->N_TA_offset = 624/4; + case 0: //15 kHz scs + AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); + factor = fp->samples_per_subframe / 30720.0; + break; + case 1: //30 kHz sc + AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); + factor = fp->samples_per_subframe / 30720.0; + break; + case 2: //60 kHz scs + AssertFatal(1==0, "scs_common should not be 60 kHz\n"); + break; + case 3: //120 kHz scs + AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; + break; + case 4: //240 kHz scs + AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; + break; + default: + AssertFatal(1==0, "Invalid scs_common!\n"); } - if (frame_parms->threequarter_fs == 1) factor = factor*.75; + ru->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor, - config->carrier_config.uplink_frequency.value, N_RB); + + LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d, mu %d)\n",ru->idx,ru->N_TA_offset,factor, + config->carrier_config.uplink_frequency.value, N_RB, mu); } else ru->N_TA_offset = 0; @@ -1301,136 +1137,61 @@ void *ru_stats_thread(void *param) { return(NULL); } -void *ru_thread_tx( void *param ) { - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - PHY_VARS_gNB *gNB; - gNB_L1_proc_t *gNB_proc; - gNB_L1_rxtx_proc_t *L1_proc; - char filename[40]; - int print_frame = 8; - int i = 0; - int ret; - +void ru_tx_func(void *param) { - wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - printf( "ru_thread_tx ready\n"); + processingData_RU_t *info = (processingData_RU_t *) param; + RU_t *ru = info->ru; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + int frame_tx = info->frame_tx; + int slot_tx = info->slot_tx; + int print_frame = 8; + char filename[40]; - while (!oai_exit) { + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,slot_tx); - LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n"); - // wait until eNBs are finished subframe RX n and TX n+4 + // do OFDM with/without TX front-end processing if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,slot_tx); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 ); - wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 ); + if(!emulate_rf) { + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,slot_tx,info->timestamp_tx); - ret = pthread_mutex_lock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock return %d\n",ret); - int frame_tx=proc->frame_tx; - int tti_tx =proc->tti_tx; - uint64_t timestamp_tx = proc->timestamp_tx; + if (ru->fh_north_out) ru->fh_north_out(ru); + } else { + if(frame_tx == print_frame) { + for (int i=0; inb_tx; i++) { - ret = pthread_mutex_unlock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); + if(slot_tx == 0) { + sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, slot_tx); + LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - if (oai_exit) break; + sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, slot_tx); + LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx ); - - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx); - - if(!emulate_rf) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - - if(proc->tti_tx == 0) { - sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - - sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); - } - - if(proc->tti_tx == 9) { - sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); - LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); - sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); - FILE *output_fd = fopen(filename,"w"); - - if (output_fd) { - fwrite(&ru->common.txdata[i][0], - sizeof(int32_t), - fp->samples_per_frame, - output_fd); - fclose(output_fd); - } else { - LOG_E(PHY,"Cannot write to file %s\n",filename); - } - }//if(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs); - - for(i = 0; inum_gNB; i++) { - gNB = ru->gNB_list[i]; - gNB_proc = &gNB->proc; - L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc; - ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - - for (int j=0; jnum_RU; j++) { - if (ru == gNB->RU_list[j]) { - if ((gNB_proc->RU_mask_tx&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx); - - gNB_proc->RU_mask_tx |= (1<common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); } - } - if (gNB_proc->RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } else { // all RUs TX are finished so send the ready signal to gNB processing - gNB_proc->RU_mask_tx = 0; - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); + if(slot_tx == 9) { + sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); + LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); + sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); + FILE *output_fd = fopen(filename,"w"); - ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - // the thread can now be woken up - if (L1_proc->instance_cnt_RUs == -1) { - L1_proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); - AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, - "ERROR pthread_cond_signal for gNB_L1_thread\n"); - } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); - ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } - } - } - - release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - return 0; + if (output_fd) { + fwrite(&ru->common.txdata[i][0], + sizeof(int32_t), + fp->samples_per_frame, + output_fd); + fclose(output_fd); + } else { + LOG_E(PHY,"Cannot write to file %s\n",filename); + } + }//if(slot_tx == 9) + }//for (i=0; inb_tx; i++) + }//if(frame_tx == print_frame) + }//else emulate_rf } void *ru_thread( void *param ) { @@ -1438,12 +1199,11 @@ void *ru_thread( void *param ) { RU_t *ru = (RU_t *)param; RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; + PHY_VARS_gNB *gNB = RC.gNB[0]; int ret; int slot = fp->slots_per_frame-1; int frame = 1023; - char filename[40], threadname[40]; - int print_frame = 8; - int i = 0; + char threadname[40]; int aa; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -1503,6 +1263,15 @@ void *ru_thread( void *param ) { pthread_mutex_unlock(&RC.ru_mutex); wait_sync("ru_thread"); + notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func); + notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1_tx,tx_func); + notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func); + processingData_L1_t *syncMsg; + notifiedFIFO_elt_t *res; + pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning + pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning + pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning + if(!emulate_rf) { // Start RF device if any if (ru->start_rf) { @@ -1511,19 +1280,6 @@ void *ru_thread( void *param ) { else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); - // if an asnych_rxtx thread exists - // wakeup the thread because the devices are ready at this point - - if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) { - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx=0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); - } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); - - // if this is a slave RRU, try to synchronize on the DL frequency - if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); - // start trx write thread if(usrp_tx_thread == 1){ if (ru->start_write_thread){ @@ -1537,11 +1293,6 @@ void *ru_thread( void *param ) { } } - pthread_mutex_lock(&proc->mutex_FH1); - proc->instance_cnt_FH1 = 0; - pthread_mutex_unlock(&proc->mutex_FH1); - pthread_cond_signal(&proc->cond_FH1); - // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices struct timespec slot_start; clock_gettime(CLOCK_MONOTONIC, &slot_start); @@ -1585,24 +1336,17 @@ void *ru_thread( void *param ) { if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot); else AssertFatal(1==0, "No fronthaul interface at south port"); + proc->timestamp_tx = proc->timestamp_rx + (sf_ahead*fp->samples_per_subframe); + proc->frame_tx = (proc->tti_rx > (fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (proc->frame_rx+1)&1023 : proc->frame_rx; + proc->tti_tx = (proc->tti_rx + (fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; + LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", frame,slot, proc->frame_rx,proc->tti_rx, proc->frame_tx,proc->tti_tx, RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); - /* - LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", - ru->do_prach, - is_prach_subframe(fp, proc->frame_rx, proc->tti_rx), - proc->frame_rx,proc->tti_rx); + RC.gNB[0]->proc.frame_tx); - if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) { - wakeup_prach_ru(ru); - }*/ - - // adjust for timing offset between RU - //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx); if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; // do RX front-end processing (frequency-shift, dft) if needed @@ -1615,7 +1359,6 @@ void *ru_thread( void *param ) { if (slot == 8) slot_type = NR_UPLINK_SLOT; if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { - //if (proc->tti_rx==8) { if (ru->feprx) { ru->feprx(ru,proc->tti_rx); @@ -1665,50 +1408,17 @@ void *ru_thread( void *param ) { } // At this point, all information for subframe has been received on FH interface + res = pullTpool(gNB->resp_L1, gNB->threadPool); + syncMsg = (processingData_L1_t *)NotifiedFifoData(res); + syncMsg->gNB = gNB; + syncMsg->frame_rx = proc->frame_rx; + syncMsg->slot_rx = proc->tti_rx; + syncMsg->frame_tx = proc->frame_tx; + syncMsg->slot_tx = proc->tti_tx; + syncMsg->timestamp_tx = proc->timestamp_tx; + res->key = proc->tti_rx; + pushTpool(gNB->threadPool, res); - // wakeup all gNB processes waiting for this RU - if (ru->num_gNB>0) wakeup_gNB_L1s(ru); - - if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) { - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx); - - if(!emulate_rf) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1); - - if(proc->tti_tx == 9) { - sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); - LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); - sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); - FILE *output_fd = fopen(filename,"w"); - - if (output_fd) { - fwrite(&ru->common.txdata[i][0], - sizeof(int32_t), - fp->samples_per_frame, - output_fd); - fclose(output_fd); - } else { - LOG_E(PHY,"Cannot write to file %s\n",filename); - } - }//if(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - proc->emulate_rf_busy = 0; - }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) } printf( "Exiting ru_thread \n"); @@ -1719,85 +1429,13 @@ void *ru_thread( void *param ) { else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); } + delNotifiedFIFO_elt(msg); + delNotifiedFIFO_elt(msgL1Tx); + delNotifiedFIFO_elt(msgRUTx); + ru_thread_status = 0; return &ru_thread_status; } -/* -// This thread run the initial synchronization like a UE -void *ru_thread_synch(void *arg) { - - RU_t *ru = (RU_t*)arg; - NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; - int32_t sync_pos,sync_pos2; - uint32_t peak_val; - uint32_t sync_corr[307200] __attribute__((aligned(32))); - static int ru_thread_synch_status; - - - - wait_sync("ru_thread_synch"); - - // initialize variables for PSS detection - lte_sync_time_init(ru->nr_frame_parms); - - while (!oai_exit) { - - // wait to be woken up - if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break; - - // if we're not in synch, then run initial synch - if (ru->in_synch == 0) { - // run intial synch like UE - LOG_I(PHY,"Running initial synchronization\n"); - - sync_pos = lte_sync_time_gNB(ru->common.rxdata, - fp, - fp->samples_per_subframe*5, - &peak_val, - sync_corr); - LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val); - - if (sync_pos >= 0) { - if (sync_pos >= fp->nb_prefix_samples) - sync_pos2 = sync_pos - fp->nb_prefix_samples; - else - sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples; - - if (fp->frame_type == FDD) { - - // PSS is hypothesized in last symbol of first slot in Frame - int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples; - - if (sync_pos2 >= sync_pos_slot) - ru->rx_offset = sync_pos2 - sync_pos_slot; - else - ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot; - } - else { - - } - - LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset); - - if ((peak_val > 300000) && (sync_pos > 0)) { - // if (sync_pos++ > 3) { - write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2); - write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1); - exit(-1); - } - - ru->in_synch=1; - } - } - - if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break; - } // oai_exit - - ru_thread_synch_status = 0; - return &ru_thread_synch_status; - -} -*/ int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) { return(ru->ifdevice.trx_start_func(&ru->ifdevice)); @@ -1819,17 +1457,10 @@ int start_write_thread(RU_t *ru) { void init_RU_proc(RU_t *ru) { int i=0; RU_proc_t *proc; - char name[100]; LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); proc = &ru->proc; memset((void *)proc,0,sizeof(RU_proc_t)); proc->ru = ru; - proc->instance_cnt_prach = -1; - proc->instance_cnt_synch = -1; - proc->instance_cnt_FH = -1; - proc->instance_cnt_FH1 = -1; - proc->instance_cnt_gNBs = -1; - proc->instance_cnt_asynch_rxtx = -1; proc->instance_cnt_emulateRF = -1; proc->first_rx = 1; proc->first_tx = 1; @@ -1840,44 +1471,13 @@ void init_RU_proc(RU_t *ru) { for (i=0; i<10; i++) proc->symbol_mask[i]=0; - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); - pthread_mutex_init( &proc->mutex_synch,NULL); - pthread_mutex_init( &proc->mutex_FH,NULL); - pthread_mutex_init( &proc->mutex_FH1,NULL); pthread_mutex_init( &proc->mutex_emulateRF,NULL); - pthread_mutex_init( &proc->mutex_gNBs, NULL); - pthread_cond_init( &proc->cond_prach, NULL); - pthread_cond_init( &proc->cond_FH, NULL); - pthread_cond_init( &proc->cond_FH1, NULL); pthread_cond_init( &proc->cond_emulateRF, NULL); - pthread_cond_init( &proc->cond_asynch_rxtx, NULL); - pthread_cond_init( &proc->cond_synch,NULL); - pthread_cond_init( &proc->cond_gNBs, NULL); threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX ); - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) - threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT ); - if(emulate_rf) threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); - if (ru->function == NGFI_RRU_IF4p5) { - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT ); - ///tmp deactivation of synch thread - // if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT ); - - snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); - pthread_setname_np( proc->pthread_FH, name ); - } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF - LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT ); - } - if (get_thread_worker_conf() == WORKER_ENABLE) { if (ru->feprx) nr_init_feprx_thread(ru); @@ -1890,46 +1490,9 @@ void init_RU_proc(RU_t *ru) { void kill_NR_RU_proc(int inst) { RU_t *ru = RC.ru[inst]; RU_proc_t *proc = &ru->proc; - pthread_mutex_lock(&proc->mutex_FH); - proc->instance_cnt_FH = 0; - pthread_mutex_unlock(&proc->mutex_FH); - pthread_cond_signal(&proc->cond_FH); - pthread_mutex_lock(&proc->mutex_prach); - proc->instance_cnt_prach = 0; - pthread_mutex_unlock(&proc->mutex_prach); - pthread_cond_signal(&proc->cond_prach); - pthread_mutex_lock(&proc->mutex_synch); - proc->instance_cnt_synch = 0; - pthread_mutex_unlock(&proc->mutex_synch); - pthread_cond_signal(&proc->cond_synch); - pthread_mutex_lock(&proc->mutex_gNBs); - proc->instance_cnt_gNBs = 0; - pthread_mutex_unlock(&proc->mutex_gNBs); - pthread_cond_signal(&proc->cond_gNBs); - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx = 0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); LOG_D(PHY, "Joining pthread_FH\n"); pthread_join(proc->pthread_FH, NULL); - if (ru->function == NGFI_RRU_IF4p5) { - LOG_D(PHY, "Joining pthread_prach\n"); - pthread_join(proc->pthread_prach, NULL); - - if (ru->is_slave) { - LOG_D(PHY, "Joining pthread_\n"); - pthread_join(proc->pthread_synch, NULL); - } - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) { - LOG_D(PHY, "Joining pthread_asynch_rxtx\n"); - pthread_join(proc->pthread_asynch_rxtx, NULL); - } - } - if (get_nprocs() >= 2) { if (ru->feprx) { pthread_mutex_lock(&proc->mutex_fep); @@ -1958,17 +1521,6 @@ void kill_NR_RU_proc(int inst) { LOG_D(PHY, "Joining ru_stats_thread\n"); pthread_join(ru->ru_stats_thread, NULL); } - - pthread_mutex_destroy(&proc->mutex_prach); - pthread_mutex_destroy(&proc->mutex_asynch_rxtx); - pthread_mutex_destroy(&proc->mutex_synch); - pthread_mutex_destroy(&proc->mutex_FH); - pthread_mutex_destroy(&proc->mutex_gNBs); - pthread_cond_destroy(&proc->cond_prach); - pthread_cond_destroy(&proc->cond_FH); - pthread_cond_destroy(&proc->cond_asynch_rxtx); - pthread_cond_destroy(&proc->cond_synch); - pthread_cond_destroy(&proc->cond_gNBs); } int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 924c32b8a7..69fc3c554d 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -136,9 +136,6 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; double rx_gain_off = 0.0; -double sample_rate=30.72e6; -double bw = 10.0e6; - static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/; @@ -476,93 +473,6 @@ void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], } } -/* -void init_openair0(void) { - - int card; - int i; - - for (card=0; cardrf_config.dl_carrier_bandwidth.value == 100) { - if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=23.04e6; - openair0_cfg[card].samples_per_frame = 230400; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } else { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; - } - } else if(config[0]->rf_config.dl_carrier_bandwidth.value == 50) { - openair0_cfg[card].sample_rate=15.36e6; - openair0_cfg[card].samples_per_frame = 153600; - openair0_cfg[card].tx_bw = 5e6; - openair0_cfg[card].rx_bw = 5e6; - } else if (config[0]->rf_config.dl_carrier_bandwidth.value == 25) { - openair0_cfg[card].sample_rate=7.68e6; - openair0_cfg[card].samples_per_frame = 76800; - openair0_cfg[card].tx_bw = 2.5e6; - openair0_cfg[card].rx_bw = 2.5e6; - } else if (config[0]->rf_config.dl_carrier_bandwidth.value == 6) { - openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_frame = 19200; - openair0_cfg[card].tx_bw = 1.5e6; - openair0_cfg[card].rx_bw = 1.5e6; - } - - - if (config[0]->subframe_config.duplex_mode.value==TDD) - openair0_cfg[card].duplex_mode = duplex_mode_TDD; - else //FDD - openair0_cfg[card].duplex_mode = duplex_mode_FDD; - - printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, - RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value, - RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - openair0_cfg[card].Mod_id = 0; - - openair0_cfg[card].num_rb_dl=config[0]->rf_config.dl_carrier_bandwidth.value; - - openair0_cfg[card].clock_source = clock_source; - - - openair0_cfg[card].tx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - openair0_cfg[card].rx_num_channels=min(2,RC.gNB[0]->gNB_config.rf_config.tx_antenna_ports.value ); - - for (i=0; i<4; i++) { - - if (irx_total_gain_dB; - - - openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file; - printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n", - card,i, openair0_cfg[card].tx_gain[i], - openair0_cfg[card].rx_gain[i], - openair0_cfg[card].tx_freq[i], - openair0_cfg[card].rx_freq[i]); - } - } // for loop on cards -} -*/ - void wait_RUs(void) { LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask); // wait for all RUs to be configured over fronthaul diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 6be23582b1..f175ab4980 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -237,43 +237,6 @@ static void UE_synch(void *arg) { openair0_cfg[UE->rf_map.card].rx_freq[0], openair0_cfg[UE->rf_map.card].tx_freq[0]); - // reconfigure for potentially different bandwidth - switch(UE->frame_parms.N_RB_DL) { - case 6: - openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; - openair0_cfg[UE->rf_map.card].rx_bw =.96e6; - openair0_cfg[UE->rf_map.card].tx_bw =.96e6; - // openair0_cfg[0].rx_gain[0] -= 12; - break; - - case 25: - openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; - openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; - openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; - // openair0_cfg[0].rx_gain[0] -= 6; - break; - - case 50: - openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; - openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; - openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; - // openair0_cfg[0].rx_gain[0] -= 3; - break; - - case 100: - openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; - openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; - openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; - // openair0_cfg[0].rx_gain[0] -= 0; - break; - - case 66: - openair0_cfg[UE->rf_map.card].sample_rate=122.88e6; - openair0_cfg[UE->rf_map.card].rx_bw=100.e6; - openair0_cfg[UE->rf_map.card].tx_bw=100.e6; - break; - } - if (UE->mode != loop_through_memory) { UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); @@ -703,16 +666,23 @@ void *UE_thread(void *arg) { int flags = 0; int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - RX_NB_TH; - uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots; - uint8_t num_UL_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots + - (mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0); - uint8_t first_tx_slot = tdd_period - num_UL_slots; - if (slot_tx_usrp%tdd_period==first_tx_slot) - flags=2; - else if (slot_tx_usrp%tdd_period==first_tx_slot+num_UL_slots-1) - flags = 3; - else if (slot_tx_usrp%tdd_period>first_tx_slot) + + if (openair0_cfg[0].duplex_mode == duplex_mode_TDD) { + + uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots; + int nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSlots != 0); + uint8_t first_tx_slot = tdd_period - num_UL_slots; + + if (slot_tx_usrp % tdd_period == first_tx_slot) + flags = 2; + else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1) + flags = 3; + else if (slot_tx_usrp % tdd_period > first_tx_slot) + flags = 1; + } else { flags = 1; + } if (flags || IS_SOFTMODEM_RFSIM) AssertFatal( writeBlockSize == diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 5d651344d6..2854457eee 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -145,7 +145,6 @@ int chain_offset = 0; int card_offset = 0; uint64_t num_missed_slots = 0; // counter for the number of missed slots int transmission_mode = 1; -int numerology = 0; int usrp_tx_thread = 0; int oaisim_flag = 0; int emulate_rf = 0; @@ -316,92 +315,10 @@ void init_openair0(void) { for (card=0; cardthreequarter_fs; - numerology = frame_parms->numerology_index; - - if(frame_parms->N_RB_DL == 66) { - if (numerology==3) { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } else { - LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n"); - exit(-1); - } - }else if(frame_parms->N_RB_DL == 32) { - if (numerology==3) { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } else { - LOG_E(PHY,"Unsupported numerology! FR2 supports only 120KHz SCS for now.\n"); - exit(-1); - } - }else if(frame_parms->N_RB_DL == 217) { - if (numerology==1) { - if (frame_parms->threequarter_fs) { - openair0_cfg[card].sample_rate=92.16e6; - openair0_cfg[card].samples_per_frame = 921600; - } - else { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms->N_RB_DL == 273) { - if (numerology==1) { - if (frame_parms->threequarter_fs) { - AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); - } - else { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms->N_RB_DL == 106) { - if (numerology==0) { - if (frame_parms->threequarter_fs) { - openair0_cfg[card].sample_rate=23.04e6; - openair0_cfg[card].samples_per_frame = 230400; - } else { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - } - } else if (numerology==1) { - if (frame_parms->threequarter_fs) { - openair0_cfg[card].sample_rate=46.08e6; - openair0_cfg[card].samples_per_frame = 460800; - } - else { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } - } else if (numerology==2) { - openair0_cfg[card].sample_rate=122.88e6; - openair0_cfg[card].samples_per_frame = 1228800; - } else { - LOG_E(PHY,"Unsupported numerology!\n"); - exit(-1); - } - } else if(frame_parms->N_RB_DL == 50) { - openair0_cfg[card].sample_rate=15.36e6; - openair0_cfg[card].samples_per_frame = 153600; - } else if (frame_parms->N_RB_DL == 25) { - openair0_cfg[card].sample_rate=7.68e6; - openair0_cfg[card].samples_per_frame = 76800; - } else if (frame_parms->N_RB_DL == 6) { - openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_frame = 19200; - } - else { - LOG_E(PHY,"Unknown NB_RB %d!\n",frame_parms->N_RB_DL); - exit(-1); - } + openair0_cfg[card].configFilename = NULL; + openair0_cfg[card].threequarter_fs = frame_parms->threequarter_fs; + openair0_cfg[card].sample_rate = frame_parms->samples_per_subframe * 1e3; + openair0_cfg[card].samples_per_frame = frame_parms->samples_per_frame; if (frame_parms->frame_type==TDD) openair0_cfg[card].duplex_mode = duplex_mode_TDD; @@ -415,8 +332,9 @@ void init_openair0(void) { openair0_cfg[card].tx_num_channels = min(2, frame_parms->nb_antennas_tx); openair0_cfg[card].rx_num_channels = min(2, frame_parms->nb_antennas_rx); - LOG_I(PHY, "HW: Configuring card %d, tx/rx num_channels %d/%d, duplex_mode %s\n", + LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n", card, + openair0_cfg[card].sample_rate, openair0_cfg[card].tx_num_channels, openair0_cfg[card].rx_num_channels, duplex_mode[openair0_cfg[card].duplex_mode]); @@ -531,7 +449,8 @@ int main( int argc, char **argv ) { fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); - init_symbol_rotation(&UE[CC_id]->frame_parms, UE[CC_id]->frame_parms.dl_CarrierFreq); + + init_symbol_rotation(&UE[CC_id]->frame_parms); init_nr_ue_vars(UE[CC_id], 0, abstraction_flag); #ifdef FR2_TEST diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 60a761c732..7a7be1de96 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -244,6 +244,13 @@ extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr); extern void set_softmodem_sighandler(void); extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +extern uint16_t sl_ahead; +extern uint16_t sf_ahead; +extern volatile int oai_exit; + +void tx_func(void *param); +void rx_func(void *param); +void ru_tx_func(void *param); extern uint8_t nfapi_mode; #ifdef __cplusplus } diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 92057186e2..e744fcbb24 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -2406,36 +2406,3 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //free(ind.rx_indication_body.rx_pdu_list); return retval; } - -//NR UPLINK INDICATION - -int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; - return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind); -} - -int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; - return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind); -} - -int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION; - return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind); -} - -int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; - return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind); -} - -int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { - ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION; - return nfapi_pnf_p7_nr_rach_ind(p7_config_g, ind); -} - diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 85f1efa3f4..bc5e7af45f 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -1516,11 +1516,10 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_of_pdus; - nfapi_nr_rx_data_pdu_t *pdu_list; //changed from pointer to struct - gokul + nfapi_nr_rx_data_pdu_t* pdu_list; } nfapi_nr_rx_data_indication_t; @@ -1543,7 +1542,6 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_crcs; @@ -1681,7 +1679,6 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t num_ucis; @@ -1718,7 +1715,6 @@ typedef struct typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; @@ -1751,7 +1747,6 @@ typedef struct{ typedef struct { - nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index a97e4ccaaf..5f8e6b52b4 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -307,7 +307,6 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - printf("packing pdsch pdu. \n"); nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; // TODO: resolve the packaging of array (currently sending a single element) @@ -3354,308 +3353,6 @@ static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_ } -//NR UPLINK indication function packing - -//RX DATA INDICATION - -static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; - - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->harq_id, ppWritePackedMsg, end) && - push16(value->pdu_length, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - - return 1; -} - - -static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!pack_nr_rx_data_indication_body(pNfapiMsg->pdu_list,ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - -//NR CRC INDICATION - -static uint8_t pack_nr_crc_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; - - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->harq_id, ppWritePackedMsg, end) && - push8(value->tb_crc_status, ppWritePackedMsg, end) && - push16(value->num_cb, ppWritePackedMsg, end) && - //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - - return 1; -} - -static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumber_crcs;i++) - { - if(!pack_nr_crc_indication_body(pNfapiMsg->crc_list,ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - -//SRS INDICATION - -static uint8_t pack_nr_srs_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; - - if(!(push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push8(value->num_symbols, ppWritePackedMsg, end) && - push8(value->wide_band_snr, ppWritePackedMsg, end) && - push8(value->num_reported_symbols, ppWritePackedMsg, end) && - push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end) - )) - return 0; - for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) - { - if(!(push8(value->reported_symbol_list->rb_list->rb_snr, ppWritePackedMsg, end) - )) - return 0; - } - return 1; -} - -static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - -//RACH INDICATION - -static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; - - if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) && - push8(value->symbol_index, ppWritePackedMsg, end) && - push8(value->slot_index, ppWritePackedMsg, end) && - push8(value->freq_index, ppWritePackedMsg, end) && - push8(value->avg_rssi, ppWritePackedMsg, end) && - push8(value->avg_snr, ppWritePackedMsg, end) && - push8(value->num_preamble, ppWritePackedMsg, end) - )) - return 0; - for(int i = 0; i < value->num_preamble; i++) - { - if(!(push8(value->preamble_list->preamble_index, ppWritePackedMsg, end) && - push16(value->preamble_list->timing_advance, ppWritePackedMsg, end) && - push32(value->preamble_list->preamble_pwr, ppWritePackedMsg, end) - )) - return 0; - } - return 1; -} - -static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - - -//UCI INDICATION - -static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; - - if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && - push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->pucch_format, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - if (value->pduBitmap & 0x01) { //SR - if(!(push8(value->sr->sr_indication, ppWritePackedMsg, end) && - push8(value->sr->sr_confidence_level, ppWritePackedMsg, end) - )) - return 0; - } - - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if(!(push8(value->harq->num_harq, ppWritePackedMsg, end) && - push8(value->harq->harq_confidence_level, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; iharq->num_harq;i++) - { - if(!(push8(value->harq->harq_list[i].harq_value, ppWritePackedMsg, end) - )) - return 0; - } - } - - return 1; -} - -static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; - - if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && - push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->pucch_format, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end) && - push16(value->rssi, ppWritePackedMsg, end) - )) - return 0; - - if (value->pduBitmap & 0x01) { //SR - if(!(push8(value->sr.sr_bit_len, ppWritePackedMsg, end) && - pusharray8(value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, ppWritePackedMsg, end) - )) - return 0; - } - - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if(!(push8(value->harq.harq_crc, ppWritePackedMsg, end) && - push8(value->harq.harq_bit_len, ppWritePackedMsg, end) && - pusharray8(value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, ppWritePackedMsg, end) - )) - return 0; - } - - if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 - if(!(push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end) && - push8(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end) && - pusharray8(value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, ppWritePackedMsg, end) - )) - return 0; - } - - if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 - if(!(push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end) && - push8(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end) && - pusharray8(value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, ppWritePackedMsg, end) - )) - return 0; - } - - return 1; -} - -static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; - - if(!(push16(value->pdu_type, ppWritePackedMsg, end) && - push16(value->pdu_size, ppWritePackedMsg, end) - )) - return 0; - - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); - break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; - pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end); - break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end); - break; - } - } - - return 1; -} - -static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; - - if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && - push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inum_ucis;i++) - { - if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end)) - return 0; - } - -return 1; -} // Main pack function - public @@ -3700,7 +3397,6 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - printf("result of pack dl_tti_req is %d. \n",result); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: @@ -3721,24 +3417,49 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_HARQ_INDICATION: + result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_CRC_INDICATION: + result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_RX_ULSCH_INDICATION: + //printf("RX ULSCH\n"); + result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_RACH_INDICATION: + result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_SRS_INDICATION: + result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_SR_INDICATION: + result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_CQI_INDICATION: + result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_INDICATION: + result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NB_HARQ_INDICATION: + result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NRACH_INDICATION: + result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: @@ -3854,6 +3575,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu switch (pMessageHeader->message_id) { case NFAPI_DL_CONFIG_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -3861,6 +3583,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_TX_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_HI_DCI0_REQUEST: @@ -3884,6 +3607,7 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu break; case NFAPI_RX_ULSCH_INDICATION: + //printf("RX ULSCH\n"); result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -6348,334 +6072,6 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * return 1; } - -//UNPACK NR UPLINK INDICATION FUNCTIONS - -//RX DATA INDICATION - -static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; - - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->harq_id, end) && - pull16(ppReadPackedMsg, &value->pdu_length, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - return 1; -} - - -static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - // uint8_t *ptr = *ppReadPackedMsg; - // printf("\n Read P7 message rx data indication unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); - nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - - printf("\n"); - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end)) - return 0; - } - -return 1; -} - -//NR CRC INDICATION - -static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; - - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->harq_id, end) && - pull8(ppReadPackedMsg, &value->tb_crc_status, end) && - pull16(ppReadPackedMsg, &value->num_cb, end) && - //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - - return 1; -} - -static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t *ptr = *ppReadPackedMsg; - // printf("\n Read P7 message indication unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) - )) - return 0; - - for(int i=0; inumber_crcs;i++) - { - if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end)) - return 0; - } - -return 1; -} - -//SRS INDICATION - -static uint8_t unpack_nr_srs_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; - - if(!(pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull8(ppReadPackedMsg, &value->num_symbols, end) && - pull8(ppReadPackedMsg, &value->wide_band_snr, end) && - pull8(ppReadPackedMsg, &value->num_reported_symbols, end) && - pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end) - )) - return 0; - for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) - { - if(!(pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list->rb_snr, end) - )) - return 0; - } - return 1; -} - -static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) && - pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end) - )) - return 0; - - for(int i=0; inumber_of_pdus;i++) - { - if(!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) - return 0; - } - -return 1; -} - -//NR RACH - -static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && - pull8(ppReadPackedMsg, &value->symbol_index, end) && - pull8(ppReadPackedMsg, &value->slot_index, end) && - pull8(ppReadPackedMsg, &value->freq_index, end) && - pull8(ppReadPackedMsg, &value->avg_rssi, end) && - pull8(ppReadPackedMsg, &value->avg_snr, end) && - pull8(ppReadPackedMsg, &value->num_preamble, end) - )) - return 0; - for(int i = 0; i < value->num_preamble; i++) - { - if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && - pull16(ppReadPackedMsg, &value->preamble_list->timing_advance, end) && - pull32(ppReadPackedMsg, &value->preamble_list->preamble_pwr, end) - )) - return 0; - } - return 1; -} - -static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { - - nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) - )) - return 0; - - for(int i=0; i< pNfapiMsg->number_of_pdus;i++) - { - if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) - return 0; - } - -return 1; -} - -//NR UCI - -static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; - - uint8_t *ptr = *ppReadPackedMsg; - printf("\n Read P7 message uci_0_1 indication unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); - - if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && - pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->pucch_format, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - if (value->pduBitmap & 0x01) { //SR - if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && - pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) - )) - return 0; - } - - // if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - // uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value - // temp = (uint8_t*) malloc(sizeof(uint8_t)); - // //printf("value->harq->num_harq = %d \n", value->harq->num_harq); - // // if(!(pull8(ppReadPackedMsg, temp, end) && - // // pull8(ppReadPackedMsg, temp, end) - // // )) - // // return 0; - - // // for(int i=0; i<1;i++) - // // { - // // if(!(pull8(ppReadPackedMsg, temp, end) //review - gokul - // // )) - // // return 0; - // // } - // } - - return 1; -} - - -static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; - - if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && - pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->pucch_format, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull16(ppReadPackedMsg, &value->rssi, end) - )) - return 0; - if (value->pduBitmap & 0x01) { //SR - if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) && - pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) - )) - return 0; - } - - if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) && - pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) && - pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) - )) - return 0; - } - - if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 - if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) && - pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) && - pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) - )) - return 0; - } - - if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 - if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) && - pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) && - pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) - )) - return 0; - } - - return 1; -} - -static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && - pull16(ppReadPackedMsg, &value->pdu_size, end) - )) - return 0; - - switch (value->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); - break; - - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; - unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end); - break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end); - break; - } - } - - return 1; -} - -static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end) - )) - return 0; - - for(int i=0; inum_ucis;i++) - { - if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end)) - return 0; - } - -return 1; -} - - static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { uint8_t proceed = 1; @@ -8301,32 +7697,62 @@ static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBuf if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) retLen = sizeof(nfapi_nr_tx_data_request_t); break; - - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) - retLen = sizeof(nfapi_nr_rx_data_indication_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) - retLen = sizeof(nfapi_nr_crc_indication_t); + + case NFAPI_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) + retLen = sizeof(nfapi_harq_indication_t); break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) - retLen = sizeof(nfapi_nr_rach_indication_t); + case NFAPI_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) + retLen = sizeof(nfapi_crc_indication_t); break; - - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) - retLen = sizeof(nfapi_nr_uci_indication_t); + + case NFAPI_RX_ULSCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) + retLen = sizeof(nfapi_rx_indication_t); break; - - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) - retLen = sizeof(nfapi_nr_srs_indication_t); + + case NFAPI_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) + retLen = sizeof(nfapi_rach_indication_t); break; - + + case NFAPI_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) + retLen = sizeof(nfapi_srs_indication_t); + break; + + case NFAPI_RX_SR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) + retLen = sizeof(nfapi_sr_indication_t); + break; + + case NFAPI_RX_CQI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) + retLen = sizeof(nfapi_cqi_indication_t); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) + retLen = sizeof(nfapi_lbt_dl_config_request_t); + break; + + case NFAPI_LBT_DL_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) + retLen = sizeof(nfapi_lbt_dl_indication_t); + break; + + case NFAPI_NB_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) + retLen = sizeof(nfapi_nb_harq_indication_t); + break; + + case NFAPI_NRACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) + retLen = sizeof(nfapi_nrach_indication_t); + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) retLen = sizeof(nfapi_nr_dl_node_sync_t); @@ -8636,15 +8062,15 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); return -1; } - - // uint8_t *ptr = pMessageBuf; - // printf("\n Read P7 message unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); - + /* + uint8_t *ptr = pMessageBuf; + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); +*/ // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); @@ -8710,41 +8136,83 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) - result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_HARQ_INDICATION: + if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) - result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + case NFAPI_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) + result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); else return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) - result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_RX_ULSCH_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) - result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) - result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + case NFAPI_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; + case NFAPI_RX_SR_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_CQI_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_INDICATION: + if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NB_HARQ_INDICATION: + if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NRACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 14b4846846..3511ed2fb9 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1572,7 +1572,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, { NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); - + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); }//Need to add more cases diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 88aa1391cb..efcb60ce96 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -175,7 +175,17 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t pnf_p7_t* _this = (pnf_p7_t*)(config); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); } +int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); +} int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) { if(config == NULL || ind == NULL) @@ -255,65 +265,3 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } - -//NR UPLINK INDICATION - -int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) -{ - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } - - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); -} - -int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind) -{ - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } - - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); -} - -int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind) -{ - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } - - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); -} - -int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind) -{ - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } - - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); -} - -int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) -{ - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } - - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); -} diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index ad1c5e7944..248faf8369 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -24,8 +24,6 @@ #define TIMEHR_USEC(_time_hr) ((uint32_t)(_time_hr) & 0xFFFFF) #define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF)) - - typedef struct { uint8_t* buffer; uint16_t length; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 453f0f3769..39f7899d77 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -461,7 +461,6 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno); } - return 0; } @@ -677,7 +676,6 @@ int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_inf //dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr); dl_node_sync.t1 = calculate_nr_t1(p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr); dl_node_sync.delta_sfn_slot = 0; - return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header); } @@ -1453,102 +1451,8 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) phy->previous_t1 = ind.t1; phy->previous_t2 = ind.t2; } -} -//NR HANDLES FOR UPLINK MESSAGES -void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_rx_data_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - - } -} - -void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_crc_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - - } -} - -void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_srs_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - - } -} - -void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_uci_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - } -} - -void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - // ensure it's valid - if (pRecvMsg == NULL || vnf_p7 == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); - } - else - { - nfapi_nr_rach_indication_t ind; - - if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); - } - - } } void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) @@ -2131,26 +2035,46 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_HARQ_INDICATION: + vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - vnf_handle_nr_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_CRC_INDICATION: + vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - vnf_handle_nr_uci_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_RX_ULSCH_INDICATION: + vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_RACH_INDICATION: + vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_SRS_INDICATION: + vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); break; + case NFAPI_RX_SR_INDICATION: + vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_RX_CQI_INDICATION: + vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_LBT_DL_INDICATION: + vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NB_HARQ_INDICATION: + vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NRACH_INDICATION: + vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + case NFAPI_UE_RELEASE_RESPONSE: vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7); break; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 3fa1f035fd..aba91d0d28 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -26,8 +26,12 @@ #include "vnf_p7.h" +#include "common/ran_context.h" + +#include "openair1/PHY/defs_gNB.h" #define FAPI2_IP_DSCP 0 +extern RAN_CONTEXT_t RC; nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create() { @@ -93,6 +97,7 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // send indications to mac int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) { + uint16_t vnf_frame; uint8_t vnf_slot; if(config == 0) return -1; @@ -145,7 +150,7 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) //struct timespec original_pselect_timeout; struct timespec pselect_timeout; - pselect_timeout.tv_sec = 0; + pselect_timeout.tv_sec = 0; pselect_timeout.tv_nsec = 500000; // ns in a 0.5 ms //pselect_timeout.tv_nsec = 500000; @@ -257,7 +262,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) //long wraps = pselect_timeout.tv_nsec % 1e9; - + // pselect_timeout.tv_sec = 100; // 0 + // pselect_timeout.tv_nsec = 0;//500000; // ns in a 0.5 ms selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); // selectRetval = pselect(120, &rfds, NULL, NULL, &pselect_timeout, NULL); @@ -388,6 +394,8 @@ NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d] selectRetval = 0; } + nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; + uint8_t ul_p7_count = 0; if(selectRetval == 0) { //vnf_p7->sf_start_time_hr = vnf_get_current_time_hr(); @@ -395,7 +403,7 @@ NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d] struct timespec current_time; clock_gettime(CLOCK_MONOTONIC, ¤t_time); // pselect timed out - nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; + while(curr != 0) { if (curr->slot == 19) @@ -410,17 +418,49 @@ struct timespec current_time; { curr->slot++; } + //printf("Frame = %d, slot = %d in VNF main loop. n",curr->sfn,curr->slot); + vnf_frame = curr->sfn; vnf_slot = curr->slot; + + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",vnf_frame,vnf_slot,curr_time.tv_sec,curr_time.tv_nsec); + vnf_nr_sync(vnf_p7, curr); curr = curr->next; } send_mac_slot_indications(vnf_p7); + + + + // // Call the scheduler + // struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + // pthread_mutex_lock(&gNB->UL_INFO_mutex); + // gNB->UL_INFO.frame = vnf_frame; + // gNB->UL_INFO.slot = vnf_slot; + + // gNB->UL_INFO.module_id = gNB->Mod_id; + // gNB->UL_INFO.CC_id = gNB->CC_id; + // gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + // pthread_mutex_unlock(&gNB->UL_INFO_mutex); } else if(selectRetval > 0) { // have a p7 message if(FD_ISSET(vnf_p7->socket, &rfds)) - { + { + vnf_nr_p7_read_dispatch_message(vnf_p7); + + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); } } else diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index d00bc90315..0e6b253c2b 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -20,6 +20,7 @@ */ #include "executables/nr-softmodem-common.h" +#include "common/utils/nr/nr_common.h" #include "PHY/defs_gNB.h" #include "PHY/phy_extern.h" #include "PHY/NR_REFSIG/nr_refsig.h" @@ -45,10 +46,42 @@ #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" -/* -extern uint32_t from_nrarfcn(int nr_bandP,uint32_t dl_nrarfcn); -extern openair0_config_t openair0_cfg[MAX_CARDS]; -*/ +static +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) +{ + const uint64_t dl_freq_khz = downlink_frequency / 1000; + const int32_t delta_duplex_khz = delta_duplex / 1000; + + uint64_t center_freq_diff_khz = 999999999999999999; // 2^64 + uint16_t current_band = 0; + + for (int ind = 0; ind < nr_bandtable_size; ind++) { + + LOG_D(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min, nr_bandtable[ind].ul_min); + + if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max) + continue; + + int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min; + + if (current_offset_khz != delta_duplex_khz) + continue; + + uint64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; + + if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ + current_band = nr_bandtable[ind].band; + center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); + } + } + + LOG_I(PHY, "DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n", + downlink_frequency, current_band, downlink_frequency+delta_duplex); + + AssertFatal(current_band != 0, "Can't find EUTRA band for frequency %"PRIu64" and duplex_spacing %u\n", downlink_frequency, delta_duplex); + + return current_band; +} int l1_north_init_gNB() { @@ -431,8 +464,8 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, gNB->mac_enabled = 1; if (mu==1) { - fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); - fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); fp->nr_band = 78; // fp->threequarter_fs= 0; } else if (mu==3) { @@ -455,7 +488,6 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { uint8_t short_sequence, num_sequences, rootSequenceIndex, fd_occasion; NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id]->frame_parms; nfapi_nr_config_request_scf_t *gNB_config = &RC.gNB[Mod_id]->gNB_config; - int32_t dlul_offset = 0; memcpy((void*)gNB_config,phy_config->cfg,sizeof(*phy_config->cfg)); RC.gNB[Mod_id]->mac_enabled = 1; @@ -466,16 +498,9 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { uint64_t ul_bw_khz = (12*gNB_config->carrier_config.ul_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<ssb_config.scs_common.value); fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ; - //fp->nr_band = *RC.nrmac[Mod_id]->common_channels[0].ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - lte_frame_type_t frame_type = 0; // FDD - - get_band(fp->dl_CarrierFreq,&fp->nr_band,&dlul_offset,&frame_type); //RC.nrmac[Mod_id] cannot be accessed in NFAPI + int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; + fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset); - get_delta_duplex(fp->nr_band, gNB_config->ssb_config.scs_common.value, &dlul_offset); - dlul_offset *= 1000; - - AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + dlul_offset), "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + dlul_offset); - LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset); fp->threequarter_fs = openair0_cfg[0].threequarter_fs; @@ -504,7 +529,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { // } RC.gNB[Mod_id]->configured = 1; - init_symbol_rotation(fp,fp->dl_CarrierFreq); + init_symbol_rotation(fp); LOG_I(PHY,"gNB %d configured\n",Mod_id); } diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 8bcc58160f..3132fb9960 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -507,50 +507,36 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){ if (fp->frame_type == FDD) { ue->N_TA_offset = 0; } else { - int N_RB = fp->N_RB_DL; int N_TA_offset = fp->ul_CarrierFreq < 6e9 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 - double factor = 1; + + double factor = 1.0; switch (fp->numerology_index) { case 0: //15 kHz scs AssertFatal(N_TA_offset == 400, "scs_common 15kHz only for FR1\n"); - if (N_RB <= 25) factor = .25; // 7.68 Ms/s - else if (N_RB <=50) factor = .5; // 15.36 Ms/s - else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s - else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s - else AssertFatal(1==0, "Too many PRBS for mu=0\n"); + factor = fp->samples_per_subframe / 30720.0; break; case 1: //30 kHz sc AssertFatal(N_TA_offset == 400, "scs_common 30kHz only for FR1\n"); - if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s - else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s + factor = fp->samples_per_subframe / 30720.0; break; case 2: //60 kHz scs AssertFatal(1==0, "scs_common should not be 60 kHz\n"); break; case 3: //120 kHz scs AssertFatal(N_TA_offset == 431, "scs_common 120kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; break; case 4: //240 kHz scs - AssertFatal(1==0, "scs_common should not be 60 kHz\n"); - if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s - else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s - else AssertFatal(1==0, "N_RB %d is too big for curretn FR2 implementation\n", N_RB); + AssertFatal(N_TA_offset == 431, "scs_common 240kHz only for FR2\n"); + factor = fp->samples_per_subframe / 61440.0; break; - - if (N_RB == 100) - ue->N_TA_offset = 624; - else if (N_RB == 50) - ue->N_TA_offset = 624/2; - else if (N_RB == 25) - ue->N_TA_offset = 624/4; + default: + AssertFatal(1==0, "Invalid scs_common!\n"); } - if (fp->threequarter_fs == 1) - factor = factor*.75; - ue->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, N_RB); + LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d, mu %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index); } } diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index ba4147e5cd..bacc671adc 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -75,9 +75,8 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp) return symbol; } -void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw) +void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL) { - switch(mu) { case NR_MU_0: //15kHz scs @@ -99,108 +98,17 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw) else AssertFatal(1==0,"NR Operating Band n%d not available for SS block SCS with mu=%d\n", fp->nr_band, mu); } - - switch(bw){ - case 5: - case 15: - case 20: - case 25: - case 30: - case 40: //40 MHz - if (fp->threequarter_fs) { - fp->ofdm_symbol_size = 1536; - fp->first_carrier_offset = 900; //1536 - ( (106*12) / 2 ) - fp->nb_prefix_samples0 = 132; - fp->nb_prefix_samples = 108; - } - else { - fp->ofdm_symbol_size = 2048; - fp->first_carrier_offset = 1412; //2048 - ( (106*12) / 2 ) - fp->nb_prefix_samples0 = 176; - fp->nb_prefix_samples = 144; - } - break; - - case 50: - case 60: - case 70: - - case 80: //80 MHz - if (fp->threequarter_fs) { - fp->ofdm_symbol_size = 3072; - fp->first_carrier_offset = 1770; //3072 - ( (217*12) / 2 ) - fp->nb_prefix_samples0 = 264; - fp->nb_prefix_samples = 216; - } - else { - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2794; //4096 - ( (217*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - } - break; - - case 90: - AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for %d MHz band and MU %d\n",bw,mu); - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2626; //4096 - ( (245*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - break; - case 100: - AssertFatal(fp->threequarter_fs==0,"3/4 sampling impossible for %d MHz band and MU %d\n",bw,mu); - fp->ofdm_symbol_size = 4096; - fp->first_carrier_offset = 2458; //4096 - ( (273*12) / 2 ) - fp->nb_prefix_samples0 = 352; - fp->nb_prefix_samples = 288; - break; - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); - } break; case NR_MU_2: //60kHz scs fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_2]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_2]; - - switch(bw){ //FR1 bands only - case 10: - case 15: - case 20: - case 25: - case 30: - case 40: - case 50: - case 60: - case 70: - case 80: - case 90: - case 100: - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); - } break; case NR_MU_3: fp->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_3]; fp->slots_per_subframe = nr_slots_per_subframe[NR_MU_3]; fp->ssb_type = nr_ssb_type_D; - switch(bw){ - case 100: - fp->ofdm_symbol_size = 1024; - fp->first_carrier_offset = 628; //1024 - ( (66*12) / 2 ) - fp->nb_prefix_samples0 = 136; - fp->nb_prefix_samples = 72; - break; - case 50: - fp->ofdm_symbol_size = 512; - fp->first_carrier_offset = 320; //1024 - ( (66*12) / 2 ) - fp->nb_prefix_samples0 = 68; - fp->nb_prefix_samples = 36; - break; - default: - AssertFatal(1==0,"%d MHz band undefined for mu %d, frame parms = %p\n", bw, mu, fp); - } break; case NR_MU_4: @@ -209,9 +117,21 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, uint16_t bw) fp->ssb_type = nr_ssb_type_E; break; - default: - AssertFatal(1==0,"Invalid numerology index %d", mu); + default: + AssertFatal(1==0,"Invalid numerology index %d", mu); } + + if(fp->threequarter_fs) + fp->ofdm_symbol_size = 3 * 128; + else + fp->ofdm_symbol_size = 4 * 128; + + while(fp->ofdm_symbol_size < N_RB_DL * 12) + fp->ofdm_symbol_size <<= 1; + + fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2); + fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9; + fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu)); } uint32_t get_samples_per_slot(int slot, NR_DL_FRAME_PARMS* fp) @@ -280,7 +200,7 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, fp->half_frame_bit = 0; // half frame bit initialized to 0 here fp->numerology_index = mu; - set_scs_parameters(fp, mu, cfg->carrier_config.dl_bandwidth.value); + set_scs_parameters(fp, mu, fp->N_RB_DL); fp->slots_per_frame = 10* fp->slots_per_subframe; @@ -352,9 +272,8 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->N_RB_UL = config->carrier_config.ul_grid_size[fp->numerology_index]; fp->N_RB_DL = config->carrier_config.dl_grid_size[fp->numerology_index]; - int32_t uplink_frequency_offset = 0; - get_delta_duplex(fp->nr_band, fp->numerology_index, &uplink_frequency_offset); - get_frame_type(fp->nr_band, fp->numerology_index, &fp->frame_type); + fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); + int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); uplink_frequency_offset *= 1000; LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); @@ -374,7 +293,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->Ncp = Ncp; - set_scs_parameters(fp,fp->numerology_index,config->carrier_config.dl_bandwidth); + set_scs_parameters(fp, fp->numerology_index, fp->N_RB_DL); fp->slots_per_frame = 10* fp->slots_per_subframe; fp->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats diff --git a/openair1/PHY/MODULATION/modulation_UE.h b/openair1/PHY/MODULATION/modulation_UE.h index 72a1334fe9..20fdaa7ad8 100644 --- a/openair1/PHY/MODULATION/modulation_UE.h +++ b/openair1/PHY/MODULATION/modulation_UE.h @@ -51,16 +51,13 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, int nr_slot_fep(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, unsigned char l, - unsigned char Ns, - int sample_offset, - int no_prefix); + unsigned char Ns); int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix); + int sample_offset); int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, unsigned char l, diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index ed9a859fb6..f12dcfc01b 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -591,35 +591,63 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) } -void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq) { +void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) { + + uint64_t dl_CarrierFreq = fp->dl_CarrierFreq; + uint64_t ul_CarrierFreq = fp->ul_CarrierFreq; + double f[2] = {(double)dl_CarrierFreq, (double)ul_CarrierFreq}; const int nsymb = fp->symbols_per_slot * fp->slots_per_frame/10; const double Tc=(1/480e3/4096); const double Nu=2048*64*(1/(float)(1<numerology_index)); - const double f0= (double)CarrierFreq; const double Ncp0=16*64 + (144*64*(1/(float)(1<numerology_index))); const double Ncp1=(144*64*(1/(float)(1<numerology_index))); - double tl=0,poff,exp_re,exp_im; - double Ncp,Ncpm1=Ncp0; - poff = 2*M_PI*((Ncp0*Tc))*f0; - exp_re = cos(poff); - exp_im = sin(-poff); - fp->symbol_rotation[0]=(int16_t)floor(exp_re*32767); - fp->symbol_rotation[1]=(int16_t)floor(exp_im*32767); - LOG_I(PHY,"Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n",f0,nsymb); - LOG_I(PHY,"Symbol rotation %d/%d => (%d,%d)\n",0,nsymb,fp->symbol_rotation[0],fp->symbol_rotation[1]); - for (int l=1;lnumerology_index))) Ncp=Ncp0; - else Ncp=Ncp1; - tl += (Nu+Ncpm1)*Tc; - poff = 2*M_PI*(tl + (Ncp*Tc))*f0; - exp_re = cos(poff); - exp_im = sin(-poff); - fp->symbol_rotation[l<<1]=(int16_t)floor(exp_re*32767); - fp->symbol_rotation[1+(l<<1)]=(int16_t)floor(exp_im*32767); - LOG_I(PHY,"Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n",l,nsymb,tl,fp->symbol_rotation[l<<1],fp->symbol_rotation[1+(l<<1)], - (poff/2/M_PI)-floor(poff/2/M_PI)); - Ncpm1=Ncp; + for (uint8_t ll = 0; ll < 2; ll++){ + + double f0 = f[ll]; + double Ncpm1 = Ncp0; + int16_t *symbol_rotation = fp->symbol_rotation[ll]; + + double tl = 0; + double poff = 2 * M_PI * ((Ncp0 * Tc)) * f0; + double exp_re = cos(poff); + double exp_im = sin(-poff); + symbol_rotation[0] = (int16_t)floor(exp_re * 32767); + symbol_rotation[1] = (int16_t)floor(exp_im * 32767); + LOG_I(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb); + LOG_I(PHY, "Symbol rotation %d/%d => (%d,%d)\n", + 0, + nsymb, + symbol_rotation[0], + symbol_rotation[1]); + + for (int l = 1; l < nsymb; l++) { + + double Ncp; + if (l == (7 * (1 << fp->numerology_index))) { + Ncp = Ncp0; + } else { + Ncp = Ncp1; + } + + tl += (Nu + Ncpm1) * Tc; + poff = 2 * M_PI * (tl + (Ncp * Tc)) * f0; + exp_re = cos(poff); + exp_im = sin(-poff); + symbol_rotation[l<<1] = (int16_t)floor(exp_re * 32767); + symbol_rotation[1 + (l<<1)] = (int16_t)floor(exp_im * 32767); + + LOG_I(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n", + l, + nsymb, + tl, + symbol_rotation[l<<1], + symbol_rotation[1 + (l<<1)], + (poff / 2 / M_PI) - floor(poff / 2 / M_PI)); + + Ncpm1 = Ncp; + + } } } diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 3d2be905ac..841073a1af 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -74,7 +74,6 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue, \param symbol symbol within slot (0..12/14) \param Ns Slot number (0..19) \param sample_offset offset within rxdata (points to beginning of subframe) -\param no_prefix if 1 prefix is removed by HW */ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, @@ -82,8 +81,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix); + int sample_offset); /*! \brief This function implements the dft transform precoding in PUSCH @@ -110,7 +108,7 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, int nsymb, int length); -void init_symbol_rotation(NR_DL_FRAME_PARMS *fp,uint64_t CarrierFreq); +void init_symbol_rotation(NR_DL_FRAME_PARMS *fp); void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 2d86b46742..8cf9f05b9b 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -306,15 +306,23 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, int length) { int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot; + int16_t *symbol_rotation = fp->symbol_rotation[0]; + for (int sidx=0;sidxsymbol_rotation[2*(sidx+first_symbol+symb_offset)],fp->symbol_rotation[1+2*(sidx+first_symbol+symb_offset)]); - rotate_cpx_vector(trxdata+(sidx*length*2), - &fp->symbol_rotation[2*(sidx+first_symbol+symb_offset)], - trxdata+(sidx*length*2), - length, - 15); + first_symbol + sidx, + slot, + sidx + first_symbol + symb_offset, + length, + symbol_rotation[2 * (sidx + first_symbol + symb_offset)], + symbol_rotation[1 + 2 * (sidx + first_symbol + symb_offset)]); + + rotate_cpx_vector(trxdata + (sidx * length * 2), + &symbol_rotation[2 * (sidx + first_symbol + symb_offset)], + trxdata + (sidx * length * 2), + length, + 15); } } diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 60b28d4ad1..0be635ba0b 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -29,364 +29,121 @@ //#define DEBUG_FEP -#define SOFFSET 0 - /*#ifdef LOG_I #undef LOG_I #define LOG_I(A,B...) printf(A) #endif*/ +dft_size_idx_t get_dft_size_idx(uint16_t ofdm_symbol_size) +{ + switch (ofdm_symbol_size) { + case 128: + return DFT_128; + + case 256: + return DFT_256; + + case 512: + return DFT_512; + + case 1024: + return DFT_1024; + + case 1536: + return DFT_1536; + + case 2048: + return DFT_2048; + + case 3072: + return DFT_3072; + + case 4096: + return DFT_4096; + + case 6144: + return DFT_6144; + + case 8192: + return DFT_8192; + + default: + printf("unsupported ofdm symbol size \n"); + assert(0); + } + + return DFT_SIZE_IDXTABLESIZE; +} + int nr_slot_fep(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, unsigned char symbol, - unsigned char Ns, - int sample_offset, - int no_prefix) + unsigned char Ns) { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - NR_UE_COMMON *common_vars = &ue->common_vars; - unsigned char aa; + NR_UE_COMMON *common_vars = &ue->common_vars; + + AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); + AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1); + unsigned int nb_prefix_samples; unsigned int nb_prefix_samples0; - unsigned int abs_symbol; if (ue->is_synchronized) { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); - } - else { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - } - //unsigned int subframe_offset;//,subframe_offset_F; - unsigned int slot_offset; - //int i; - unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10; - unsigned int rx_offset; - - - dft_size_idx_t dftsize; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs - - switch (frame_parms->ofdm_symbol_size) { - case 128: - dftsize = DFT_128; - break; - - case 256: - dftsize = DFT_256; - break; - - case 512: - dftsize = DFT_512; - break; - - case 1024: - dftsize = DFT_1024; - break; - - case 1536: - dftsize = DFT_1536; - break; - - case 2048: - dftsize = DFT_2048; - break; - - case 3072: - dftsize = DFT_3072; - break; - - case 4096: - dftsize = DFT_4096; - break; - - case 8192: - dftsize = DFT_8192; - break; - - default: - printf("unsupported ofdm symbol size \n"); - assert(0); - } - - if (no_prefix) { - slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns); + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples0; } else { - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples; } - /*if (l<0 || l>=7-frame_parms->Ncp) { - printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); - return(-1); - }*/ + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); - if (Ns<0 || Ns>(frame_parms->slots_per_frame-1)) { - printf("slot_fep: Ns must be between 0 and %d\n",frame_parms->slots_per_frame-1); - return(-1); - } + unsigned int rx_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; + for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) + rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rx_offset += frame_parms->ofdm_symbol_size * symbol; - for (aa=0; aanb_antennas_rx; aa++) { - memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); - - rx_offset = sample_offset + slot_offset - SOFFSET; - // Align with 256 bit - // rx_offset = rx_offset&0xfffffff8; + // use OFDM symbol from within 1/8th of the CP to avoid ISI + rx_offset -= nb_prefix_samples / 8; #ifdef DEBUG_FEP - // if (ue->frame <100) - /*LOG_I(PHY,*/printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", - Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, rx_offset %u\n", + Ns, symbol, nb_prefix_samples, nb_prefix_samples0, rx_offset); #endif - abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; - - for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb < abs_symbol; idx_symb++) - rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + for (unsigned char aa=0; aanb_antennas_rx; aa++) { + memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t)); - rx_offset += frame_parms->ofdm_symbol_size * symbol; - - if (abs_symbol%(0x7<numerology_index)) { - - rx_offset += nb_prefix_samples; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short*) &common_vars->rxdata[aa][frame_length_samples], - (short*) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); - - if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset % frame_length_samples], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif - } - } else { - - rx_offset += nb_prefix_samples0; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((void *) &common_vars->rxdata[aa][frame_length_samples], - (void *) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly - - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif + int16_t *rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset]; + // if input to dft is not 256-bit aligned + if ((rx_offset & 7) != 0) { + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + frame_parms->ofdm_symbol_size * sizeof(int32_t)); + rxdata_ptr = (int16_t *)tmp_dft_in; } -#ifdef DEBUG_FEP - // if (ue->frame <100) - printf("slot_fep: symbol %d rx_offset %u\n", symbol, rx_offset); -#endif - - int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset]; - ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; - rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - (int16_t*)&rot2, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - frame_parms->ofdm_symbol_size, - 15); - - } - - -#ifdef DEBUG_FEP - printf("slot_fep: done\n"); -#endif - return(0); -} - -int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - unsigned char Ns, - int sample_offset, - int no_prefix) -{ - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - NR_UE_COMMON *common_vars = &ue->common_vars; - unsigned char aa; - unsigned int nb_prefix_samples; - unsigned int nb_prefix_samples0; - unsigned int abs_symbol; - if (ue->is_synchronized) { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); - } - else { - nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - } - //unsigned int subframe_offset;//,subframe_offset_F; - unsigned int slot_offset; - //int i; - unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10; - unsigned int rx_offset; - - - dft_size_idx_t dftsize; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs - - switch (frame_parms->ofdm_symbol_size) { - case 128: - dftsize = DFT_128; - break; - - case 256: - dftsize = DFT_256; - break; - - case 512: - dftsize = DFT_512; - break; - - case 1024: - dftsize = DFT_1024; - break; - - case 1536: - dftsize = DFT_1536; - break; - - case 2048: - dftsize = DFT_2048; - break; - - case 3072: - dftsize = DFT_3072; - break; - - case 4096: - dftsize = DFT_4096; - break; - - case 8192: - dftsize = DFT_8192; - break; - - default: - printf("unsupported ofdm symbol size \n"); - assert(0); - } - - if (no_prefix) { - slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_slot) * (Ns); - } else { - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - } - - /*if (l<0 || l>=7-frame_parms->Ncp) { - printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); - return(-1); - }*/ - - if (Ns<0 || Ns>(frame_parms->slots_per_frame-1)) { - printf("slot_fep: Ns must be between 0 and %d\n",frame_parms->slots_per_frame-1); - return(-1); - } - - for (aa=0; aanb_antennas_rx; aa++) { - memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); - - rx_offset = sample_offset + slot_offset - SOFFSET; - // Align with 256 bit - // rx_offset = rx_offset&0xfffffff8; - -#ifdef DEBUG_FEP - // if (ue->frame <100) - /*LOG_I(PHY,*/printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", - Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); -#endif - - abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; - - for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb < abs_symbol; idx_symb++) - rx_offset += (abs_symbol%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; - - rx_offset += frame_parms->ofdm_symbol_size * symbol; - - if (abs_symbol%(0x7<numerology_index)) { - - rx_offset += nb_prefix_samples; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short*) &common_vars->rxdata[aa][frame_length_samples], - (short*) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); - - if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly #if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); + start_meas(&ue->rx_dft_stats); #endif + dft(dftsize, + rxdata_ptr, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + 1); - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][rx_offset], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); + stop_meas(&ue->rx_dft_stats); #endif - } - } else { - - rx_offset += nb_prefix_samples0; - if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((void *) &common_vars->rxdata[aa][frame_length_samples], - (void *) &common_vars->rxdata[aa][0], - frame_parms->ofdm_symbol_size*sizeof(int)); -#if UE_TIMING_TRACE - start_meas(&ue->rx_dft_stats); -#endif - - if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs - memcpy((void *)tmp_dft_in, - (void *) &common_vars->rxdata[aa][rx_offset], - frame_parms->ofdm_symbol_size*sizeof(int)); - dft(dftsize,(int16_t *)tmp_dft_in, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } else { // use dft input from RX buffer directly - dft(dftsize,(int16_t *) &common_vars->rxdata[aa][rx_offset], - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); - } -#if UE_TIMING_TRACE - stop_meas(&ue->rx_dft_stats); -#endif - - - } int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation)[symbol+symb_offset]; + int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol+symb_offset]; ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; #ifdef DEBUG_FEP @@ -400,14 +157,121 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], frame_parms->ofdm_symbol_size, 15); - } - #ifdef DEBUG_FEP printf("slot_fep: done\n"); #endif - return(0); + + return 0; +} + +int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + unsigned char symbol, + unsigned char Ns, + int sample_offset) +{ + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + NR_UE_COMMON *common_vars = &ue->common_vars; + + AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); + AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1); + + unsigned int nb_prefix_samples; + unsigned int nb_prefix_samples0; + if (ue->is_synchronized) { + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples0; + } + else { + nb_prefix_samples = frame_parms->nb_prefix_samples; + nb_prefix_samples0 = frame_parms->nb_prefix_samples; + } + unsigned int frame_length_samples = frame_parms->samples_per_frame; + + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); + + unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); + unsigned int rx_offset = sample_offset + slot_offset; + unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; + for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) + rx_offset += (abs_symbol%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; + rx_offset += frame_parms->ofdm_symbol_size * symbol; + +#ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d, nb_prefix_samples %u, nb_prefix_samples0 %u, slot_offset %u, sample_offset %d,rx_offset %u, frame_length_samples %u\n", + Ns, symbol, nb_prefix_samples, nb_prefix_samples0, slot_offset, sample_offset, rx_offset, frame_length_samples); +#endif + + for (unsigned char aa=0; aanb_antennas_rx; aa++) { + memset(&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int32_t)); + + int16_t *rxdata_ptr; + + if (frame_length_samples - rx_offset < frame_parms->ofdm_symbol_size) { + + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + (frame_length_samples - rx_offset) * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[frame_length_samples - rx_offset], + (void *)&common_vars->rxdata[aa][0], + (frame_parms->ofdm_symbol_size - (frame_length_samples - rx_offset)) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)&tmp_dft_in[0]; + + } else if ((rx_offset & 7) != 0) { + + // if input to dft is not 256-bit aligned + memcpy((void *)&tmp_dft_in[0], + (void *)&common_vars->rxdata[aa][rx_offset], + frame_parms->ofdm_symbol_size * sizeof(int32_t)); + rxdata_ptr = (int16_t *)&tmp_dft_in[0]; + + } else { + + // use dft input from RX buffer directly + rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset]; + + } + +#if UE_TIMING_TRACE + start_meas(&ue->rx_dft_stats); +#endif + + dft(dftsize, + rxdata_ptr, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + 1); + +#if UE_TIMING_TRACE + stop_meas(&ue->rx_dft_stats); +#endif + + int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; + int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset]; + ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + +#ifdef DEBUG_FEP + // if (ue->frame <100) + printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset, + symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); +#endif + + rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + (int16_t*)&rot2, + (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + frame_parms->ofdm_symbol_size, + 15); + } + +#ifdef DEBUG_FEP + printf("slot_fep: done\n"); +#endif + + return 0; } @@ -416,89 +280,60 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, int32_t *rxdataF, unsigned char symbol, unsigned char Ns, - int sample_offset, - int no_prefix) + int sample_offset) { - int32_t slot_offset, rxdata_offset; - - unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); - unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); + unsigned int nb_prefix_samples = frame_parms->nb_prefix_samples; + unsigned int nb_prefix_samples0 = frame_parms->nb_prefix_samples0; - int tmp_dft_in[8192] __attribute__ ((aligned (32))); + dft_size_idx_t dftsize = get_dft_size_idx(frame_parms->ofdm_symbol_size); + // This is for misalignment issues + int32_t tmp_dft_in[8192] __attribute__ ((aligned (32))); - dft_size_idx_t dftsize; + unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - switch (frame_parms->ofdm_symbol_size) { - case 128: - dftsize = DFT_128; - break; + // offset of first OFDM symbol + int32_t rxdata_offset = slot_offset + nb_prefix_samples0; + // offset of n-th OFDM symbol + rxdata_offset += symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples); + // use OFDM symbol from within 1/8th of the CP to avoid ISI + rxdata_offset -= nb_prefix_samples / 8; - case 256: - dftsize = DFT_256; - break; + int16_t *rxdata_ptr; - case 512: - dftsize = DFT_512; - break; + if(sample_offset > rxdata_offset) { - case 1024: - dftsize = DFT_1024; - break; + memcpy((void *)&tmp_dft_in[0], + (void *)&rxdata[frame_parms->samples_per_frame - sample_offset + rxdata_offset], + (sample_offset - rxdata_offset) * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[sample_offset - rxdata_offset], + (void *)&rxdata[0], + (frame_parms->ofdm_symbol_size - sample_offset + rxdata_offset) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)&tmp_dft_in[0]; - case 1536: - dftsize = DFT_1536; - break; + } else if (((rxdata_offset - sample_offset) & 7) != 0) { - case 2048: - dftsize = DFT_2048; - break; + // if input to dft is not 256-bit aligned + memcpy((void *)&tmp_dft_in[0], + (void *)&rxdata[rxdata_offset - sample_offset], + (frame_parms->ofdm_symbol_size) * sizeof(int32_t)); + rxdata_ptr = (int16_t *)&tmp_dft_in[0]; - case 4096: - dftsize = DFT_4096; - break; + } else { - case 8192: - dftsize = DFT_8192; - break; + // use dft input from RX buffer directly + rxdata_ptr = (int16_t *)&rxdata[rxdata_offset - sample_offset]; - default: - dftsize = DFT_512; - break; } - - slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); - if(symbol == 0) - rxdata_offset = slot_offset + nb_prefix_samples0 - SOFFSET; - else - rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET; - - if(sample_offset>rxdata_offset) { - memcpy1((void *)tmp_dft_in, - (void *) &rxdata[frame_parms->samples_per_frame-sample_offset+rxdata_offset], - (sample_offset-rxdata_offset)*sizeof(int)); - - memcpy1((void *)&tmp_dft_in[sample_offset-rxdata_offset], - (void *) &rxdata[0], - (frame_parms->ofdm_symbol_size-sample_offset+rxdata_offset)*sizeof(int)); - - dft(dftsize,(int16_t *)&tmp_dft_in, - (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - } - else { - //dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset], - // (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - memcpy((void *)tmp_dft_in, - (void *) &rxdata[rxdata_offset-sample_offset], - (frame_parms->ofdm_symbol_size)*sizeof(int)); - dft(dftsize,(int16_t *)&tmp_dft_in, - (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); - } + dft(dftsize, + rxdata_ptr, + (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], + 1); // clear DC carrier from OFDM symbols rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0; - return(0); + return 0; } void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, @@ -513,7 +348,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, for (int symbol=0;symbolsymbol_rotation)[symbol+symb_offset]; + uint32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[1])[symbol + symb_offset]; ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); rotate_cpx_vector((int16_t *)&rxdataF[frame_parms->ofdm_symbol_size*symbol], diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index ec55eabf31..a54aec7bc2 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -37,22 +37,20 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) { - int temp, i, aa, max_pos = 0, max_val = 0; - short Re, Im; - uint8_t cyclic_shift = 0; + int i, aa, max_pos = 0, max_val = 0; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; - int sync_pos = (frame_parms->ofdm_symbol_size - cyclic_shift*frame_parms->ofdm_symbol_size/12) % (frame_parms->ofdm_symbol_size); + int sync_pos = frame_parms->nb_prefix_samples / 8; for (i = 0; i < frame_parms->ofdm_symbol_size; i++) { - temp = 0; + int temp = 0; for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; - Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; + short Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; + short Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; temp += (Re*Re/2) + (Im*Im/2); } diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 38b35dcf6d..10ac23bef0 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -61,8 +61,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, debug_ch_est = fopen("debug_ch_est.txt","w"); #endif - //uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1]; - uint8_t nushift; int **ul_ch_estimates = gNB->pusch_vars[ul_id]->ul_ch_estimates; int **rxdataF = gNB->common_vars.rxdataF; @@ -79,12 +77,17 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, uint16_t nb_rb_pusch = pusch_pdu->rb_size; -/* #ifdef DEBUG_CH - printf("PUSCH Channel Estimation : ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n", ,ch_offset,symbol_offset,gNB->frame_parms.ofdm_symbol_size, - gNB->frame_parms.Ncp,l,Ns,k, symbol); + LOG_D(PHY, "In %s: ch_offset %d, symbol_offset %d OFDM size %d, Ns = %d, k = %d symbol %d\n", + __FUNCTION__, + ch_offset, + symbol_offset, + gNB->frame_parms.ofdm_symbol_size, + Ns, + k, + symbol); #endif -*/ + switch (nushift) { case 0: fl = filt8_l0; @@ -124,9 +127,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //------------------generate DMRS------------------// - if (pusch_pdu->transform_precoding == transform_precoder_disabled) + if (pusch_pdu->transform_precoding == transform_precoder_disabled) { nr_pusch_dmrs_rx(gNB, Ns, gNB->nr_gold_pusch_dmrs[pusch_pdu->scid][Ns][symbol], &pilot[0], 1000, 0, nb_rb_pusch, pusch_pdu->rb_start*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type); - + } else { // if transform precoding or SC-FDMA is enabled in Uplink // NR_SC_FDMA supports type1 DMRS so only 6 DMRS REs per RB possible @@ -151,11 +154,15 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //------------------------------------------------// - #ifdef DEBUG_PUSCH - for (int i=0;i<(6*nb_rb_pusch);i++) - printf("%d+j*(%d)\n",((int16_t*)pilot)[2*i],((int16_t*)pilot)[1+(2*i)]); + for (int i = 0; i < (6 * nb_rb_pusch); i++) { + LOG_I(PHY, "In %s: %d + j*(%d)\n", + __FUNCTION__, + ((int16_t*)pilot)[2 * i], + ((int16_t*)pilot)[1 + (2 * i)]); + } #endif + for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { re_offset = k; /* Initializing the Resource element offset for each Rx antenna */ @@ -167,11 +174,11 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, memset(ul_ch,0,4*(gNB->frame_parms.ofdm_symbol_size)); #ifdef DEBUG_PUSCH - printf("symbol_offset %d, nushift %d\n",symbol_offset,nushift); - printf("ch est pilot addr %p RB_DL %d\n",&pilot[0], gNB->frame_parms.N_RB_UL); - printf("bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n",bwp_start_subcarrier,k,gNB->frame_parms.first_carrier_offset,nb_rb_pusch); - printf("rxF addr %p p %d\n", rxF,p); - printf("ul_ch addr %p nushift %d\n",ul_ch,nushift); + LOG_I(PHY, "In %s symbol_offset %d, nushift %d\n", __FUNCTION__, symbol_offset, nushift); + LOG_I(PHY, "In %s ch est pilot addr %p, N_RB_UL %d\n", __FUNCTION__, &pilot[0], gNB->frame_parms.N_RB_UL); + LOG_I(PHY, "In %s bwp_start_subcarrier %d, k %d, first_carrier %d, nb_rb_pusch %d\n", __FUNCTION__, bwp_start_subcarrier, k, gNB->frame_parms.first_carrier_offset, nb_rb_pusch); + LOG_I(PHY, "In %s rxF addr %p p %d\n", __FUNCTION__, rxF, p); + LOG_I(PHY, "In %s ul_ch addr %p nushift %d\n", __FUNCTION__, ul_ch, nushift); #endif //if ((gNB->frame_parms.N_RB_UL&1)==0) { @@ -182,9 +189,18 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); - printf("pilot 0 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); - printf("data 0 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); + LOG_I(PHY, "In %s ch 0 %d\n", __FUNCTION__, ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])); + LOG_I(PHY, "In %s pilot 0 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 0 : rxF - > (%d,%d) (%d)\n", __FUNCTION__, rxF[2], rxF[3], dBc(rxF[2],rxF[3])); #endif multadd_real_vector_complex_scalar(fl, @@ -201,9 +217,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); - printf("data 1 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); + LOG_I(PHY, "In %s pilot 1 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 1 : rxF - > (%d,%d) (%d)\n", + __FUNCTION__, + rxF[2], + rxF[3], + dBc(rxF[2],rxF[3])); #endif + multadd_real_vector_complex_scalar(fml, ch, ul_ch, @@ -217,9 +247,23 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); #ifdef DEBUG_PUSCH - printf("pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]); - printf("data 2 : rxF - > (%d,%d) (%d)\n",rxF[2],rxF[3],dBc(rxF[2],rxF[3])); + LOG_I(PHY, "In %s pilot 2 : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n", + __FUNCTION__, + rxF[0], + rxF[1], + dBc(rxF[0],rxF[1]), + ch[0], + ch[1], + dBc(ch[0],ch[1]), + pil[0], + pil[1]); + LOG_I(PHY, "In %s data 2 : rxF - > (%d,%d) (%d)\n", + __FUNCTION__, + rxF[2], + rxF[3], + dBc(rxF[2],rxF[3])); #endif + multadd_real_vector_complex_scalar(fmm, ch, ul_ch, diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 5d62f9dbb9..5a4b1adbb8 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -40,9 +40,9 @@ #include "PHY/defs_gNB.h" /*Table 7.4.1.1.2-1/2 from 38.211 */ -int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1}}; +int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}}; int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}}; -int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1},{1,1},{1,-1},{1,1},{1,1}}; +int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1}}; int wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}}; // complex conjugate of mod table diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 1cce5e1174..66fc987f6d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -147,19 +147,18 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, uint16_t n_dmrs; if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; - n_dmrs = ((rel15->rbSize+rel15->rbStart)*6)<<1; } else { nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; - n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1; } + n_dmrs = (rel15->rbSize+rel15->rbStart)*nb_re_dmrs; uint16_t dmrs_symbol_map = rel15->dlDmrsSymbPos;//single DMRS: 010000100 Double DMRS 110001100 uint8_t dmrs_len = get_num_dmrs(rel15->dlDmrsSymbPos); uint16_t nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs*dmrs_len-xOverhead)*rel15->rbSize*rel15->nrOfLayers; uint8_t Qm = rel15->qamModOrder[0]; uint32_t encoded_length = nb_re*Qm; - int16_t mod_dmrs[14][n_dmrs] __attribute__ ((aligned(16))); + int16_t mod_dmrs[14][n_dmrs<<1] __attribute__ ((aligned(16))); /* PTRS */ uint16_t beta_ptrs = 1; @@ -271,10 +270,10 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, /// DMRS QPSK modulation for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { if (rel15->dlDmrsSymbPos & (1 << l)) { - nr_modulation(pdsch_dmrs[l][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated + nr_modulation(pdsch_dmrs[l][0], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_DLSCH - printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs>>1, dmrs_Type); + printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs, dmrs_Type); for (int i=0; i>4; i++) { for (int j=0; j<8; j++) { printf("%d %d\t", mod_dmrs[l][((i<<3)+j)<<1], mod_dmrs[l][(((i<<3)+j)<<1)+1]); diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index b5a3c061e9..64b14091d6 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -301,205 +301,300 @@ void rx_nr_prach_ru(RU_t *ru, // do DFT if (mu==1) { - if (fp->N_RB_UL <= 100) - AssertFatal(1==0,"N_RB_UL %d not support for NR PRACH yet\n",fp->N_RB_UL); - else if (fp->N_RB_UL < 137) { - if (fp->threequarter_fs==0) { - //40 MHz @ 61.44 Ms/s - //50 MHz @ 61.44 Ms/s - prach2 = prach[aa] + (Ncp<<2); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 to bring to 61.44 Ms/s - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=49152; - dft(DFT_49152,prach2,rxsigF[aa],1); + switch(fp->samples_per_subframe) { + case 15360: + // 10, 15 MHz @ 15.36 Ms/s + prach2 = prach[aa] + (1*Ncp); // Ncp is for 30.72 Ms/s, so divide by 2 to bring to 15.36 Ms/s and multiply by 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=12288; + dft(DFT_12288,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_12288,prach2+24576,rxsigF[aa]+24576,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_12288,prach2+(24576*2),rxsigF[aa]+(24576*2),1); + dft(DFT_12288,prach2+(24576*3),rxsigF[aa]+(24576*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=3072; + for (int i=0;i<4;i++) dft(DFT_3072,prach2+(i*3072*2),rxsigF[aa]+(i*3072*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=16; // 8 samples @ 15.36 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=512; + dft(DFT_512,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_512,prach2+1024,rxsigF[aa]+1024,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_512,prach2+1024*2,rxsigF[aa]+1024*2,1); + dft(DFT_512,prach2+1024*3,rxsigF[aa]+1024*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_512,prach2+1024*4,rxsigF[aa]+1024*4,1); + dft(DFT_512,prach2+1024*5,rxsigF[aa]+1024*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_512,prach2+(1024*i),rxsigF[aa]+(1024*i),1); + reps+=6; + } } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1); - dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=12288; - for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); - reps=4; - } - }// 839 sequence - else { - if (prachStartSymbol == 0) - prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) + break; - dftlen=2048; - dft(DFT_2048,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); - reps++; - } - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1); - dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1); - dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); - reps+=6; - } - } - } else { // threequarter sampling - // 40 MHz @ 46.08 Ms/s - prach2 = prach[aa] + (3*Ncp); // 46.08 is 1.5 * 30.72, times 2 for I/Q - if (prach_sequence_length == 0) { - AssertFatal(fp->N_RB_UL <= 107,"cannot do 108..136 PRBs with 3/4 sampling\n"); - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=36864; - dft(DFT_36864,prach2,rxsigF[aa],1); - reps++; - } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1); - dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=9216; - for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); - reps=4; - } - } else { - if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only) - dftlen=1536; - dft(DFT_1536,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1); - dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1); - dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); - reps+=6; - } - } // short format - } // 3/4 sampling - } // <=50 MHz BW - else if (fp->N_RB_UL <= 273) { - if (fp->threequarter_fs==0) { - prach2 = prach[aa] + (Ncp<<3); - //80,90,100 MHz @ 122.88 Ms/s + case 30720: + // 20, 25, 30 MHz @ 30.72 Ms/s + prach2 = prach[aa] + (2*Ncp); // Ncp is for 30.72 Ms/s, so just multiply by 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=24576; + dft(DFT_24576,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_24576,prach2+49152,rxsigF[aa]+49152,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_24576,prach2+(49152*2),rxsigF[aa]+(49152*2),1); + dft(DFT_24576,prach2+(49152*3),rxsigF[aa]+(49152*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=6144; + for (int i=0;i<4;i++) dft(DFT_6144,prach2+(i*6144*2),rxsigF[aa]+(i*6144*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=32; // 16 samples @ 30.72 Ms/s in first symbol of each half subframe (15/30 kHz only) - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=98304; - dft(DFT_98304,prach2,rxsigF[aa],1); + dftlen=1024; + dft(DFT_1024,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_1024,prach2+2048,rxsigF[aa]+2048,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_1024,prach2+2048*2,rxsigF[aa]+2048*2,1); + dft(DFT_1024,prach2+2048*3,rxsigF[aa]+2048*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_1024,prach2+2048*4,rxsigF[aa]+2048*4,1); + dft(DFT_1024,prach2+2048*5,rxsigF[aa]+2048*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_1024,prach2+(2048*i),rxsigF[aa]+(2048*i),1); + reps+=6; + } } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1); - reps++; - } - if (prachFormat == 2) { - dft(DFT_98304,prach2+(196608*2),rxsigF[aa]+(196608*2),1); - dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1); - reps+=2; - } - if (prachFormat == 3) { - dftlen=24576; - for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); - reps=4; - } - } - else { - if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + break; - dftlen=4096; - dft(DFT_4096,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1); - dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1); - dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); - reps+=6; - } - } - } else { - AssertFatal(fp->N_RB_UL <= 217,"cannot do more than 217 PRBs with 3/4 sampling\n"); - prach2 = prach[aa] + (6*Ncp); - // 80 MHz @ 92.16 Ms/s - if (prach_sequence_length == 0) { - if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { - dftlen=73728; - dft(DFT_73728,prach2,rxsigF[aa],1); - reps++; - } - if (prachFormat == 1 || prachFormat == 2) { - dft(DFT_73728,prach2+(2*73728),rxsigF[aa]+(2*73728),1); - reps++; - } - if (prachFormat == 3) { - dftlen=18432; - for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); - reps=4; - } - } else { - if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + case 61440: + // 40, 50, 60 MHz @ 61.44 Ms/s + prach2 = prach[aa] + (4*Ncp); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 to bring to 61.44 Ms/s + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=49152; + dft(DFT_49152,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1); + dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=12288; + for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) - dftlen=3072; - dft(DFT_3072,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1); - dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1); - dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); - reps+=6; - } - } + dftlen=2048; + dft(DFT_2048,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1); + dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1); + dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); + reps+=6; + } + } + break; + + case 46080: + // 40 MHz @ 46.08 Ms/s + prach2 = prach[aa] + (3*Ncp); // 46.08 is 1.5 * 30.72, times 2 for I/Q + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=36864; + dft(DFT_36864,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1); + dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=9216; + for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=1536; + dft(DFT_1536,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1); + dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1); + dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); + reps+=6; + } + } + break; + + case 122880: + // 70, 80, 90, 100 MHz @ 122.88 Ms/s + prach2 = prach[aa] + (8*Ncp); + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=98304; + dft(DFT_98304,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_98304,prach2+(196608*2),rxsigF[aa]+(196608*2),1); + dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=24576; + for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); + reps=4; + } + } else { // 839 sequence + if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=4096; + dft(DFT_4096,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1); + dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1); + dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); + reps+=6; + } + } + break; + + case 92160: + // 80, 90 MHz @ 92.16 Ms/s + prach2 = prach[aa] + (6*Ncp); + if (prach_sequence_length == 0) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=73728; + dft(DFT_73728,prach2,rxsigF[aa],1); + } + if (prachFormat == 1 || prachFormat == 2) { + dft(DFT_73728,prach2+147456,rxsigF[aa]+147456,1); + reps++; + } + if (prachFormat == 2) { + dft(DFT_73728,prach2+(147456*2),rxsigF[aa]+(147456*2),1); + dft(DFT_73728,prach2+(147456*3),rxsigF[aa]+(147456*3),1); + reps+=2; + } + if (prachFormat == 3) { + dftlen=18432; + for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); + reps=4; + } + } else { + if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + + dftlen=3072; + dft(DFT_3072,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1); + dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1); + dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); + reps+=6; + } + } + break; + default: + AssertFatal(1==0,"sample_rate %f MHz not support for NR PRACH yet\n", fp->samples_per_subframe / 1000.0); } } - } else if (mu==3) { if (fp->threequarter_fs) { AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 42d6cfad7a..dd8627f0e0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -345,6 +345,7 @@ void nr_ulsch_extract_rbs_single(int32_t **rxdataF, n = 0; k_prime = 0; + rxF_ext_index = ul_ch0_ext_index = ul_ch0_index = 0; /* In RX Antenna(aarx) loop, Reset the index */ if (is_dmrs_symbol == 0) { // diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 3d2f27476a..239ae1d6d7 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1611,7 +1611,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; // estimate CQI for MAC (from antenna port 0 only) int SNRtimes10 = dB_fixed_times10(signal_energy_nodc(&rxdataF[0][(l2*frame_parms->ofdm_symbol_size)+re_offset],12*pucch_pdu->prb_size)) - (10*gNB->measurements.n0_power_tot_dB); - int cqi; + int cqi,bit_left; if (SNRtimes10 < -640) cqi=0; else if (SNRtimes10 > 635) cqi=255; else cqi=(640+SNRtimes10)/5; @@ -1635,7 +1635,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, uci_pdu->harq.harq_payload[i] = decodedPayload[0] & 255; decodedPayload[0]>>=8; } - uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<<(pucch_pdu->bit_len_harq&7))-1); + bit_left = pucch_pdu->bit_len_harq-((harq_bytes-1)<<3); + uci_pdu->harq.harq_payload[i] = decodedPayload[0] & ((1<>= pucch_pdu->bit_len_harq; } @@ -1649,6 +1650,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, // csi if (pucch_pdu->bit_len_csi_part1>0) { uci_pdu->pduBitmap|=4; + uci_pdu->csi_part1.csi_part1_bit_len=pucch_pdu->bit_len_csi_part1; int csi_part1_bytes=pucch_pdu->bit_len_csi_part1>>3; if ((pucch_pdu->bit_len_csi_part1&7) > 0) csi_part1_bytes++; uci_pdu->csi_part1.csi_part1_payload = (uint8_t*)malloc(csi_part1_bytes); @@ -1658,7 +1660,8 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & 255; decodedPayload[0]>>=8; } - uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<<(pucch_pdu->bit_len_csi_part1&7))-1); + bit_left = pucch_pdu->bit_len_csi_part1-((csi_part1_bytes-1)<<3); + uci_pdu->csi_part1.csi_part1_payload[i] = decodedPayload[0] & ((1<>= pucch_pdu->bit_len_csi_part1; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index bfec64820b..8176514eb4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -158,7 +158,6 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, if ((reg % reg_bundle_size_L) == 0) r++; } - // Get cce_list indices by reg_idx in ascending order int f_bundle_j_list_id = 0; int f_bundle_j_list_ord[NR_MAX_PDCCH_AGG_LEVEL] = {}; @@ -175,7 +174,6 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, } } - for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) { f_reg = (f_bundle_j_list_ord[reg/6]*reg_bundle_size_L)+(reg%reg_bundle_size_L); @@ -404,11 +402,12 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, c_rb = 0; for (int rb=0;rb>3] & (1<<(7-(c_rb_by6&7)))) == 0) { - c_rb+=6; - c_rb_by6 = c_rb/6; - } + c_rb+=6; + c_rb_by6 = c_rb/6; + } LOG_DDD("c_rb=%d\n",c_rb); rxF=NULL; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c index 68a206e7c7..853a3f61cf 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c @@ -38,6 +38,31 @@ //#define DEBUG_LLR_SIC +void PrintIntrinsics(char *s, char *dtype, void *x) { + if (strcmp(dtype,"int") == 0) { + int *tempb = (int *)x; + printf("%s: [%d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]); + } + if (strcmp(dtype,"short") == 0) { + short *tempb = (short *)x; + printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3], + tempb[4], tempb[5], tempb[6], tempb[7]); + } + if (strcmp(dtype,"char") == 0) { + char *tempb = (char *)x; + printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]\n", s, + tempb[0], tempb[1], tempb[2], tempb[3], tempb[4], tempb[5], tempb[6], tempb[7], + tempb[8], tempb[9],tempb[10],tempb[11],tempb[12],tempb[13],tempb[14],tempb[15]); + } + if (strcmp(dtype,"float") == 0) { + float *tempb = (float *)x; + printf("%s: [%f, %f, %f, %f]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]); + } + if (strcmp(dtype,"double") == 0) { + double *tempb = (double *)x; + printf("%s: [%f, %f]\n", s, tempb[0], tempb[1]); + } +} int16_t nr_zeros[8] __attribute__ ((aligned(16))) = {0,0,0,0,0,0,0,0}; int16_t nr_ones[8] __attribute__ ((aligned(16))) = {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; @@ -734,20 +759,45 @@ void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, for (i=0; isamples_per_frame+ue->ssb_offset, - 0); + is*fp->samples_per_frame+ue->ssb_offset); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"Calling sss detection (normal CP)\n"); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 3ab88dac0a..0ba02c6bac 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -244,86 +244,82 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ *********************************************************/ if (mu==1) { - if (fp->N_RB_UL <= 100) - AssertFatal(1 == 0, "N_RB_UL %d not support for NR PRACH yet\n", fp->N_RB_UL); - else if (fp->N_RB_UL < 137) { - if (fp->threequarter_fs == 0) { - //40 MHz @ 61.44 Ms/s - //50 MHz @ 61.44 Ms/s + switch(fp->samples_per_subframe) { + case 15360: + // 10, 15 MHz @ 15.36 Ms/s if (prach_sequence_length == 0) { if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) - dftlen = 49152; + dftlen = 12288; if (prach_fmt_id == 3) - dftlen = 12288; - } // 839 sequence - else { - switch (mu){ - case 1: - dftlen = 2048; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } + dftlen = 3072; + } else { // 839 sequence + dftlen = 512; } - } else { // threequarter sampling - // 40 MHz @ 46.08 Ms/s + break; + + case 30720: + // 20, 25, 30 MHz @ 30.72 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 24576; + if (prach_fmt_id == 3) + dftlen = 6144; + } else { // 839 sequence + dftlen = 1024; + } + break; + + case 46080: + // 40 MHz @ 46.08 Ms/s if (prach_sequence_length == 0) { - AssertFatal(fp->N_RB_UL <= 107, "cannot do 108..136 PRBs with 3/4 sampling\n"); if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) dftlen = 36864; if (prach_fmt_id == 3) dftlen = 9216; - } else { - switch (mu){ - case 1: - dftlen = 1536; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } - } // short format - } // 3/4 sampling - } // <=50 MHz BW - else if (fp->N_RB_UL <= 273) { - if (fp->threequarter_fs == 0) { - //80,90,100 MHz @ 122.88 Ms/s + } else { // 839 sequence + dftlen = 1536; + } + break; + + case 61440: + // 40, 50, 60 MHz @ 61.44 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 49152; + if (prach_fmt_id == 3) + dftlen = 12288; + } else { // 839 sequence + dftlen = 2048; + } + break; + + case 92160: + // 50, 60, 70, 80, 90 MHz @ 92.16 Ms/s + if (prach_sequence_length == 0) { + if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) + dftlen = 73728; + if (prach_fmt_id == 3) + dftlen = 18432; + } else { // 839 sequence + dftlen = 3072; + } + break; + + case 122880: + // 70, 80, 90, 100 MHz @ 122.88 Ms/s if (prach_sequence_length == 0) { if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) dftlen = 98304; if (prach_fmt_id == 3) dftlen = 24576; + } else { // 839 sequence + dftlen = 4096; } - } else { // threequarter sampling - switch (mu){ - case 1: - dftlen = 4096; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } - } else { - AssertFatal(fp->N_RB_UL <= 217, "cannot do more than 217 PRBs with 3/4 sampling\n"); - // 80 MHz @ 92.16 Ms/s - if (prach_sequence_length == 0) { - if (prach_fmt_id == 0 || prach_fmt_id == 1 || prach_fmt_id == 2) - dftlen = 73728; - if (prach_fmt_id == 3) - dftlen = 18432; - } else { - switch (mu){ - case 1: - dftlen = 3072; - break; - default: - AssertFatal(1 == 0, "Shouldn't get here\n"); - break; - } - } - } } else if (mu==3) { if (fp->threequarter_fs) @@ -425,15 +421,16 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ uint8_t use_extended_prach_prefix = 0; if(fp->numerology_index == 0) { if (prachStartSymbol == 0 || prachStartSymbol == 7) - use_extended_prach_prefix = 1; + use_extended_prach_prefix = 1; } else { if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) - use_extended_prach_prefix = 1; + use_extended_prach_prefix = 1; } - - if (fp->N_RB_UL <= 34) { //32 PRB case 61.44Msps - if (fp->threequarter_fs == 0) { + + if (mu == 3) { + switch (fp->samples_per_subframe) { + case 61440: // 32 PRB case, 61.44 Msps Ncp<<=1; //to account for 61.44Mbps // This is after cyclic prefix prach2 = prach+(Ncp<<1); //times 2 for complex samples @@ -491,13 +488,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (512*12)+Ncp; } } - } - else - AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL); - - } - else if (fp->N_RB_UL <= 68) {//66 PRB case, 122.88 Msps - if (fp->threequarter_fs == 0) { + break; + + case 122880: // 66 PRB case, 122.88 Msps Ncp<<=2; //to account for 122.88Mbps // This is after cyclic prefix prach2 = prach+(Ncp<<1); //times 2 for complex samples @@ -555,13 +548,211 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (1024*12)+Ncp; } } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } - else - AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL); - } - else if (fp->N_RB_UL < 137) { // 46.08 or 61.44 Ms/s - if (fp->threequarter_fs == 0) { // full sampling @ 61.44 Ms/s - Ncp<<=1; //to account for 61.44Mbps + } else if (mu == 1) { + switch (fp->samples_per_subframe) { + case 15360: // full sampling @ 15.36 Ms/s + Ncp = Ncp/2; // to account for 15.36 Ms/s + // This is after cyclic prefix + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_sequence_length == 0){ + if (prach_fmt_id == 0) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | + memmove(prach,prach+(12288<<1),(Ncp<<2)); + // here we have | Prefix | Prach12288 | + prach_len = 12288+Ncp; + } else if (prach_fmt_id == 1) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | empty12288 | + memmove(prach2+(12288<<1),prach2,(12288<<2)); + // here we have | empty | Prach12288 | Prach12288 | + memmove(prach,prach+(12288<<2),(Ncp<<2)); + // here we have | Prefix | Prach12288 | Prach12288 | + prach_len = (12288*2)+Ncp; + } else if (prach_fmt_id == 2) { // 24576 samples @ 30.72 Ms/s, 12288 samples @ 15.36 Ms/s + idft(IDFT_12288,prachF,prach2,1); + // here we have | empty | Prach12288 | empty12288 | empty12288 | empty12288 | + memmove(prach2+(12288<<1),prach2,(12288<<2)); + // here we have | empty | Prach12288 | Prach12288 | empty12288 | empty12288 | + memmove(prach2+(12288<<2),prach2,(12288<<3)); + // here we have | empty | Prach12288 | Prach12288 | Prach12288 | Prach12288 | + memmove(prach,prach+(12288<<3),(Ncp<<2)); + // here we have | Prefix | Prach12288 | Prach12288 | Prach12288 | Prach12288 | + prach_len = (12288*4)+Ncp; + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s, 3072 samples @ 15.36 Ms/s + idft(IDFT_3072,prachF,prach2,1); + // here we have | empty | Prach3072 | empty3072 | empty3072 | empty3072 | + memmove(prach2+(3072<<1),prach2,(3072<<2)); + // here we have | empty | Prach3072 | Prach3072 | empty3072 | empty3072 | + memmove(prach2+(3072<<2),prach2,(3072<<3)); + // here we have | empty | Prach3072 | Prach3072 | Prach3072 | Prach3072 | + memmove(prach,prach+(3072<<3),(Ncp<<2)); + // here we have | Prefix | Prach3072 | Prach3072 | Prach3072 | Prach3072 | + prach_len = (3072*4)+Ncp; + } + } else { // short PRACH sequence + if (use_extended_prach_prefix) + Ncp += 8; // 16*kappa, kappa=0.5 for 15.36 Ms/s + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_fmt_id == 9) { + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | + prach_len = (512*1)+Ncp; + } else if (prach_fmt_id == 4 || prach_fmt_id == 7) { + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | + prach_len = (512*2)+Ncp; + } else if (prach_fmt_id == 5) { // 4x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x512 + idft(IDFT_512,prachF,prach2,1); + // here we have | empty | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have | empty | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | empty512 | empty512 | empty512 | empty512 | empty512 | empty512 | + memmove(prach2+(512<<1)*6,prach2,(512<<2)*6); + // here we have | empty | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have | Prefix | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | + prach_len = (512*12)+Ncp; + } + } + break; + + case 30720: // full sampling @ 30.72 Ms/s + Ncp = Ncp*1; // to account for 30.72 Ms/s + // This is after cyclic prefix + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_sequence_length == 0){ + if (prach_fmt_id == 0) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | + memmove(prach,prach+(24576<<1),(Ncp<<2)); + // here we have | Prefix | Prach24576 | + prach_len = 24576+Ncp; + } else if (prach_fmt_id == 1) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | empty24576 | + memmove(prach2+(24576<<1),prach2,(24576<<2)); + // here we have | empty | Prach24576 | Prach24576 | + memmove(prach,prach+(24576<<2),(Ncp<<2)); + // here we have | Prefix | Prach24576 | Prach24576 | + prach_len = (24576*2)+Ncp; + } else if (prach_fmt_id == 2) { // 24576 samples @ 30.72 Ms/s + idft(IDFT_24576,prachF,prach2,1); + // here we have | empty | Prach24576 | empty24576 | empty24576 | empty24576 | + memmove(prach2+(24576<<1),prach2,(24576<<2)); + // here we have | empty | Prach24576 | Prach24576 | empty24576 | empty24576 | + memmove(prach2+(24576<<2),prach2,(24576<<3)); + // here we have | empty | Prach24576 | Prach24576 | Prach24576 | Prach24576 | + memmove(prach,prach+(24576<<3),(Ncp<<2)); + // here we have | Prefix | Prach24576 | Prach24576 | Prach24576 | Prach24576 | + prach_len = (24576*4)+Ncp; + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s + idft(IDFT_6144,prachF,prach2,1); + // here we have | empty | Prach6144 | empty6144 | empty6144 | empty6144 | + memmove(prach2+(6144<<1),prach2,(6144<<2)); + // here we have | empty | Prach6144 | Prach6144 | empty6144 | empty6144 | + memmove(prach2+(6144<<2),prach2,(6144<<3)); + // here we have | empty | Prach6144 | Prach6144 | Prach6144 | Prach6144 | + memmove(prach,prach+(6144<<3),(Ncp<<2)); + // here we have | Prefix | Prach6144 | Prach6144 | Prach6144 | Prach6144 | + prach_len = (6144*4)+Ncp; + } + } else { // short PRACH sequence + if (use_extended_prach_prefix) + Ncp += 16; // 16*kappa, kappa=1 for 30.72Msps + prach2 = prach+(2*Ncp); // times 2 for complex samples + if (prach_fmt_id == 9) { + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | + prach_len = (1024*1)+Ncp; + } else if (prach_fmt_id == 4 || prach_fmt_id == 7) { + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | + prach_len = (1024*2)+Ncp; + } else if (prach_fmt_id == 5) { // 4x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have | empty | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have | empty | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | empty1024 | + memmove(prach2+(1024<<1)*6,prach2,(1024<<2)*6); + // here we have | empty | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have | Prefix | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | + prach_len = (1024*12)+Ncp; + } + } + break; + + case 61440: // full sampling @ 61.44 Ms/s + Ncp = Ncp*2; // to account for 61.44 Ms/s // This is after cyclic prefix prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ @@ -587,7 +778,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(49152<<3),(Ncp<<2)); // here we have |Prefix | Prach49152 | Prach49152| Prach49152 | Prach49152 prach_len = (49152*4)+Ncp; - } else if (prach_fmt_id == 3) { // //6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s + } else if (prach_fmt_id == 3) { // 6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s idft(IDFT_12288,prachF,prach2,1); memmove(prach2+(12288<<1),prach2,(12288<<2)); // here we have |empty | Prach12288 | Prach12288| empty12288 | empty12288 @@ -649,7 +840,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (2048*12)+Ncp; } } - } else { // threequarter sampling @ 46.08 Ms/s + break; + + case 46080: // threequarter sampling @ 46.08 Ms/s Ncp = (Ncp*3)/2; prach2 = prach+(Ncp<<1); if (prach_sequence_length == 0){ @@ -738,9 +931,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (1536*12)+Ncp; } } - } - } else if (fp->N_RB_UL <= 273) {// 92.16 or 122.88 Ms/s - if (fp->threequarter_fs == 0) { // full sampling @ 122.88 Ms/s + break; + + case 122880: // full sampling @ 122.88 Ms/s Ncp<<=2; //to account for 122.88Mbps // This is after cyclic prefix prach2 = prach+(Ncp<<1); //times 2 for complex samples @@ -828,7 +1021,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (4096*12)+Ncp; } } - } else { // three quarter sampling @ 92.16 Ms/s + break; + + case 92160: // three quarter sampling @ 92.16 Ms/s Ncp = (Ncp*3); //to account for 92.16 Msps prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ @@ -915,6 +1110,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (3072*12)+Ncp; } } + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 464bcfcfba..aa32ecc8c9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -105,6 +105,8 @@ typedef struct { uint8_t O_ACK; /// Index of current HARQ round for this ULSCH uint8_t round; + /// Last Ndi for this harq process + uint8_t ndi; /// pointer to pdu from MAC interface (TS 36.212 V15.4.0, Sec 5.1 p. 8) unsigned char *a; /// Pointer to the payload + CRC diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c index 7cf64b28bb..76fc5f298f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ue_rf_helpers.c @@ -78,13 +78,15 @@ void nr_rf_card_config(openair0_config_t *openair0_cfg, openair0_cfg->autocal[i] = 1; - LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n", - i, - rf_chain, - openair0_cfg->tx_gain[i], - openair0_cfg->rx_gain[i], - openair0_cfg->tx_freq[i], - openair0_cfg->rx_freq[i]); + if (i < openair0_cfg->rx_num_channels) { + LOG_I(PHY, "HW: Configuring channel %d (rf_chain %d): setting tx_gain %f, rx_gain %f, tx_freq %f Hz, rx_freq %f Hz\n", + i, + rf_chain, + openair0_cfg->tx_gain[i], + openair0_cfg->rx_gain[i], + openair0_cfg->tx_freq[i], + openair0_cfg->rx_freq[i]); + } } } \ No newline at end of file diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index f6a346aee9..abb14e834b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -202,7 +202,6 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL, for (i=0; iharq_processes[i]->round=0; } - return(ulsch); } } @@ -257,7 +256,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, Ilbrm = 0; Tbslbrm = 950984; //max tbs Coderate = 0.0; - harq_process->round = nr_rv_round_map_ue[harq_process->pusch_pdu.pusch_data.rv_index]; /////////// ///////////////////////////////////////////////////////////////////////////////////////// @@ -267,8 +265,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, LOG_D(PHY,"ulsch coding nb_rb %d, Nl = %d\n", nb_rb, harq_process->pusch_pdu.nrOfLayers); LOG_D(PHY,"ulsch coding A %d G %d mod_order %d\n", A,G, mod_order); - // if (harq_process->Ndi == 1) { // this is a new packet - if (harq_process->round == 0) { // this is a new packet + if (harq_process->ndi != harq_process->pusch_pdu.pusch_data.new_data_indicator) { // this is a new packet #ifdef DEBUG_ULSCH_CODING printf("encoding thinks this is a new packet \n"); #endif @@ -415,7 +412,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, /////////// /////////////////////////////////////////////////////////////////////////////// - + harq_process->ndi = harq_process->pusch_pdu.pusch_data.new_data_indicator; } F = harq_process->F; Kr = harq_process->K; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 208901f289..3d8c975a5c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -496,13 +496,19 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; for(ap = 0; ap < Nl; ap++) { for (int s=0;s (%d.%d)\n", - s,s+symb_offset,frame_parms->symbol_rotation[2*(s+symb_offset)],frame_parms->symbol_rotation[1+(2*(s+symb_offset))]); - rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s], - &frame_parms->symbol_rotation[2*(s+symb_offset)], - (int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size*s], - frame_parms->ofdm_symbol_size, - 15); + + LOG_D(PHY,"In %s: rotating txdataF symbol %d (%d) => (%d.%d)\n", + __FUNCTION__, + s, + s + symb_offset, + frame_parms->symbol_rotation[1][2 * (s + symb_offset)], + frame_parms->symbol_rotation[1][1 + (2 * (s + symb_offset))]); + + rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], + &frame_parms->symbol_rotation[1][2 * (s + symb_offset)], + (int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], + frame_parms->ofdm_symbol_size, + 15); } } diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index cb61523852..b45c1abf0b 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -282,30 +282,6 @@ static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const in graph->iteration++; } -static void genericLogPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) { - float *values, *time; - oai_xygraph_getbuff(graph, &time, &values, len, 0); - - for (int ant=0; antmodule_id; @@ -250,7 +251,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ { Sched_INFO->DL_req->SFN = frame; Sched_INFO->DL_req->Slot = slot; - printf("DL tti Frame = %d, slot = %d. \n",frame,slot); + //printf("DL tti Frame = %d, slot = %d. \n",frame,slot); oai_nfapi_dl_tti_req(Sched_INFO->DL_req); } if (Sched_INFO->TX_req->Number_of_PDUs > 0) diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index a78b1f4805..9a71f96815 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -520,8 +520,7 @@ void nr_fep0(RU_t *ru, int first_half) { ru->common.rxdataF[aa], l, proc->tti_rx, - ru->N_TA_offset, - 0); + ru->N_TA_offset); } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+proc->tti_rx, 0); @@ -657,8 +656,7 @@ void nr_fep_full(RU_t *ru, int slot) { ru->common.rxdataF[aa], l, proc->tti_rx, - ru->N_TA_offset, - 0); + ru->N_TA_offset); } } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 7e7aff0a09..2617c4686e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -367,7 +367,6 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, int timing_advance_update, cqi; int sync_pos; - uint16_t mu = gNB->frame_parms.numerology_index; NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0]; NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; @@ -375,18 +374,10 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, // pdu->data = gNB->ulsch[ULSCH_id+1][0]->harq_processes[harq_pid]->b; sync_pos = nr_est_timing_advance_pusch(gNB, ULSCH_id); // estimate timing advance for MAC - timing_advance_update = sync_pos * (1 << mu); // scale by the used scs numerology // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size - switch (gNB->frame_parms.N_RB_DL) { - case 106: timing_advance_update /= 16; break; - case 217: timing_advance_update /= 32; break; - case 245: timing_advance_update /= 32; break; - case 273: timing_advance_update /= 32; break; - case 66: timing_advance_update /= 12; break; - case 32: timing_advance_update /= 12; break; - default: AssertFatal(0==1,"No case defined for PRB %d to calculate timing_advance_update\n",gNB->frame_parms.N_RB_DL); - } + uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; + timing_advance_update = sync_pos / bw_scaling; // put timing advance command in 0..63 range timing_advance_update += 31; @@ -517,15 +508,12 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) unsigned char aa; for(symbol = 0; symbol < (gNB->frame_parms.Ncp==EXTENDED?12:14); symbol++) { - // nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0); - for (aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) { nr_slot_fep_ul(&gNB->frame_parms, gNB->common_vars.rxdata[aa], gNB->common_vars.rxdataF[aa], symbol, slot_rx, - 0, 0); } } @@ -542,6 +530,9 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { + /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ + int pucch_decode_done = 0; + int pusch_decode_done = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); @@ -566,6 +557,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { + pucch_decode_done = 1; + nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; uint16_t num_ucis; switch (pucch_pdu->format_type) { @@ -657,7 +650,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } #endif -T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], 2048*4*14)); + pusch_decode_done = 1; uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; @@ -686,5 +679,9 @@ T(T_BENETEL, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF // figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS if ((frame_rx&127) == 0 && slot_rx==19) dump_pusch_stats(gNB); + if (pucch_decode_done || pusch_decode_done) { + T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index f516ad8639..14c174c2c0 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -132,6 +132,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, } switch (pdu_type){ + case FAPI_NR_RX_PDU_TYPE_SIB: case FAPI_NR_RX_PDU_TYPE_DLSCH: case FAPI_NR_RX_PDU_TYPE_RAR: harq_pid = dlsch0->current_harq_pid; @@ -202,20 +203,15 @@ uint8_t get_ra_PreambleIndex(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_id){ } - -// scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size -uint16_t get_bw_scaling(uint16_t nb_rb){ - uint16_t bw_scaling; - switch (nb_rb) { - case 32: bw_scaling = 4; break; - case 66: bw_scaling = 8; break; - case 106: bw_scaling = 16; break; - case 217: bw_scaling = 32; break; - case 245: bw_scaling = 32; break; - case 273: bw_scaling = 32; break; - default: abort(); - } - return bw_scaling; +// convert time factor "16 * 64 * T_c / (2^mu)" in N_TA calculation in TS38.213 section 4.2 to samples by multiplying with samples per second +// 16 * 64 * T_c / (2^mu) * samples_per_second +// = 16 * T_s / (2^mu) * samples_per_second +// = 16 * 1 / (15 kHz * 2048) / (2^mu) * (15 kHz * 2^mu * ofdm_symbol_size) +// = 16 * 1 / 2048 * ofdm_symbol_size +// = 16 * ofdm_symbol_size / 2048 +static inline +uint16_t get_bw_scaling(uint16_t ofdm_symbol_size){ + return 16 * ofdm_symbol_size / 2048; } // UL time alignment procedures: @@ -233,38 +229,18 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){ if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) { - uint8_t numerology = ue->frame_parms.numerology_index; - uint16_t bwp_ul_NB_RB = ue->frame_parms.N_RB_UL; - int factor_mu = 1 << numerology; - uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB); + uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; + uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size); - LOG_D(PHY, "In %s: applying timing advance -- frame %d -- slot %d -- UE_mode %d\n", __FUNCTION__, frame_tx, slot_tx, ue->UE_mode[gNB_id]); + ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling; - if (ue->UE_mode[gNB_id] == RA_RESPONSE){ - - ue->timing_advance = ul_time_alignment->ta_command * bw_scaling / factor_mu; - - LOG_D(PHY, "In %s: [UE %d] [%d.%d] Received (RAR) timing advance command %d new value is %u \n", - __FUNCTION__, - ue->Mod_id, - frame_tx, - slot_tx, - ul_time_alignment->ta_command, - ue->timing_advance); - - } else if (ue->UE_mode[gNB_id] == PUSCH){ - - ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling / factor_mu; - - LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n", - __FUNCTION__, - ue->Mod_id, - frame_tx, - slot_tx, - ul_time_alignment->ta_command, - ue->timing_advance); - - } + LOG_I(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n", + __FUNCTION__, + ue->Mod_id, + frame_tx, + slot_tx, + ul_time_alignment->ta_command, + ue->timing_advance); ul_time_alignment->ta_frame = -1; ul_time_alignment->ta_slot = -1; @@ -927,33 +903,19 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, int nr_slot_rx = proc->nr_slot_rx; int ret=0, ret1=0; NR_UE_PDSCH *pdsch_vars; - uint8_t is_cw0_active = 0; - uint8_t is_cw1_active = 0; - uint8_t dmrs_type, nb_re_dmrs; uint16_t dmrs_len = get_num_dmrs(dlsch0->harq_processes[dlsch0->current_harq_pid]->dlDmrsSymbPos); - uint16_t nb_symb_sch = 9; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; uint16_t number_pdus = 1; // params for UL time alignment procedure NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[eNB_id]; - uint16_t slots_per_frame = ue->frame_parms.slots_per_frame; - uint16_t slots_per_subframe = ue->frame_parms.slots_per_subframe; - uint8_t numerology = ue->frame_parms.numerology_index, mapping_type_ul, mapping_type_dl; - int ul_tx_timing_adjustment, N_TA_max, factor_mu, N_t_1, N_t_2, N_1, N_2, d_1_1 = 0, d_2_1, d; - uint8_t d_2_2 = 0;// set to 0 because there is only 1 BWP - // TODO this should corresponds to the switching time as defined in - // TS 38.133 - uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; - uint16_t nb_prefix_samples = ue->frame_parms.nb_prefix_samples; - uint32_t t_subframe = 1; // subframe duration of 1 msec - uint16_t start_symbol; - float tc_factor; - is_cw0_active = dlsch0->harq_processes[harq_pid]->status; - nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; - start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; - dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; + uint8_t is_cw0_active = dlsch0->harq_processes[harq_pid]->status; + uint16_t nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; + uint16_t start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; + uint8_t dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; + + uint8_t nb_re_dmrs; if (dmrs_type==NFAPI_NR_DMRS_TYPE1) { nb_re_dmrs = 6*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; } @@ -961,6 +923,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, nb_re_dmrs = 4*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; } + uint8_t is_cw1_active = 0; if(dlsch1) is_cw1_active = dlsch1->harq_processes[harq_pid]->status; @@ -1208,7 +1171,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, eNB_id, ue, dlsch0, number_pdus); break; case SI_PDSCH: - rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_SIB; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SIB, eNB_id, ue, dlsch0, number_pdus); break; default: break; @@ -1222,53 +1186,29 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } } - // TODO CRC check for CW0 - - // Check CRC for CW 0 - /*if (ret == (1+dlsch0->max_turbo_iterations)) { - *dlsch_errors=*dlsch_errors+1; - if(dlsch0->rnti != 0xffff){ - LOG_D(PHY,"[UE %d][PDSCH %x/%d] AbsSubframe %d.%d : DLSCH CW0 in error (rv %d,round %d, mcs %d,TBS %d)\n", - ue->Mod_id,dlsch0->rnti, - harq_pid,frame_rx,nr_slot_rx, - dlsch0->harq_processes[harq_pid]->rvidx, - dlsch0->harq_processes[harq_pid]->round, - dlsch0->harq_processes[harq_pid]->mcs, - dlsch0->harq_processes[harq_pid]->TBS); - } - } else { - if(dlsch0->rnti != 0xffff){ - LOG_D(PHY,"[UE %d][PDSCH %x/%d] AbsSubframe %d.%d : Received DLSCH CW0 (rv %d,round %d, mcs %d,TBS %d)\n", - ue->Mod_id,dlsch0->rnti, - harq_pid,frame_rx,nr_slot_rx, - dlsch0->harq_processes[harq_pid]->rvidx, - dlsch0->harq_processes[harq_pid]->round, - dlsch0->harq_processes[harq_pid]->mcs, - dlsch0->harq_processes[harq_pid]->TBS); - } - if ( LOG_DEBUGFLAG(DEBUG_UE_PHYPROC)){ - int j; - LOG_D(PHY,"dlsch harq_pid %d (rx): \n",dlsch0->current_harq_pid); - - for (j=0; jharq_processes[dlsch0->current_harq_pid]->TBS>>3; j++) - LOG_T(PHY,"%x.",dlsch0->harq_processes[dlsch0->current_harq_pid]->b[j]); - LOG_T(PHY,"\n"); - }*/ - if (ue->mac_enabled == 1) { - uint16_t bw_scaling = get_bw_scaling(ue->frame_parms.N_RB_DL); - /* Time Alignment procedure // - UE processing capability 1 // - Setting the TA update to be applied after the reception of the TA command // - Timing adjustment computed according to TS 38.213 section 4.2 // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are // computed according to sections 5.3 and 6.4 of TS 38.214 */ - factor_mu = 1 << numerology; - N_TA_max = 3846 * bw_scaling / factor_mu; + const int numerology = ue->frame_parms.numerology_index; + const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size; + const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples; + const int samples_per_subframe = ue->frame_parms.samples_per_subframe; + const int slots_per_frame = ue->frame_parms.slots_per_frame; + const int slots_per_subframe = ue->frame_parms.slots_per_subframe; + + const double tc_factor = 1.0 / samples_per_subframe; + const uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size); + + const int Ta_max = 3846; // Max value of 12 bits TA Command + const double N_TA_max = Ta_max * bw_scaling * tc_factor; /* PDSCH decoding time N_1 for processing capability 1 */ + int N_1; if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos0) N_1 = pdsch_N_1_capability_1[numerology][1]; else if (ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == pdsch_dmrs_pos1 || ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition == 2) // TODO set to pdsch_dmrs_pos2 when available @@ -1277,12 +1217,12 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, N_1 = pdsch_N_1_capability_1[numerology][3]; /* PUSCH preapration time N_2 for processing capability 1 */ - N_2 = pusch_N_2_timing_capability_1[numerology][1]; - mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType; - mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType; + const int N_2 = pusch_N_2_timing_capability_1[numerology][1]; /* d_1_1 depending on the number of PDSCH symbols allocated */ - d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH + const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH + int d_1_1 = 0; + mappingType_t mapping_type_dl = ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[0]->mappingType; if (mapping_type_dl == typeA) if (nb_symb_sch + start_symbol < 7) d_1_1 = 7 - (nb_symb_sch + start_symbol); @@ -1297,22 +1237,26 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } /* d_2_1 */ + int d_2_1; + mappingType_t mapping_type_ul = ue->pusch_config.pusch_TimeDomainResourceAllocation[0]->mappingType; if (mapping_type_ul == typeB && start_symbol != 0) d_2_1 = 0; else d_2_1 = 1; + /* d_2_2 */ + const double d_2_2 = 0.0; // set to 0 because there is only 1 BWP: TODO this should corresponds to the switching time as defined in TS 38.133 + /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */ - N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) / factor_mu; - N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) / factor_mu; + double N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; + double N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor; if (N_t_2 < d_2_2) N_t_2 = d_2_2; /* Time alignment procedure */ - // N_t_1 + N_t_2 + N_TA_max is in unit of Ts, therefore must be converted to Tc // N_t_1 + N_t_2 + N_TA_max must be in msec - tc_factor = 64 * 0.509 * 10e-7; - ul_tx_timing_adjustment = 1 + ceil(slots_per_subframe*((N_t_1 + N_t_2 + N_TA_max)*tc_factor + 0.5)/t_subframe); + const double t_subframe = 1.0; // subframe duration of 1 msec + const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe); if (ul_time_alignment->apply_ta == 1){ ul_time_alignment->ta_slot = (nr_slot_rx + ul_tx_timing_adjustment) % slots_per_frame; @@ -1326,13 +1270,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot); } } - - /*ue->total_TBS[eNB_id] = ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; - ue->total_received_bits[eNB_id] = ue->total_TBS[eNB_id] + dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS; - }*/ - - // TODO CRC check for CW1 - } } @@ -1736,9 +1673,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_slot_fep(ue, proc, (ue->symbol_offset+i)%(fp->symbols_per_slot), - nr_slot_rx, - 0, - 0); + nr_slot_rx); #if UE_TIMING_TRACE start_meas(&ue->dlsch_channel_estimation_stats); @@ -1791,9 +1726,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_slot_fep(ue, proc, l, - nr_slot_rx, - 0, - 0); + nr_slot_rx); dci_cnt = 0; for(int n_ss = 0; n_ssnb_search_space; n_ss++) { @@ -1852,9 +1785,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_slot_fep(ue, proc, m, //to be updated from higher layer - nr_slot_rx, - 0, - 0); + nr_slot_rx); } } } else { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 6784535391..4c6a02b69f 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -79,8 +79,8 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -int sf_ahead=4 ; -int sl_ahead=0; +uint16_t sf_ahead=4 ; +uint16_t sl_ahead=0; //uint8_t nfapi_mode = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; @@ -97,6 +97,21 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, return 0; } +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} + +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) +{ + return 0; +} + void rrc_data_ind( const protocol_ctxt_t *const ctxt_pP, @@ -185,14 +200,11 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } -int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { - return 0; -} - // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg); void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dmrs_arg); +extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration /* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs from command line of dlsim, does not search for CCE/PUCCH occasion but simply sets to 0 */ @@ -248,7 +260,10 @@ int main(int argc, char **argv) int i,aa;//,l; double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0; uint8_t snr1set=0; - float roundStats[50]; + double roundStats[500] = {0}; + double blerStats[500] = {0}; + double berStats[500] = {0}; + double snrStats[500] = {0}; float effRate; //float psnr; float eff_tp_check = 0.7; @@ -659,6 +674,7 @@ int main(int argc, char **argv) rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon)); NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon; + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup)); prepare_scc(rrc.carrier.servingcellconfigcommon); uint64_t ssb_bitmap; @@ -666,13 +682,18 @@ int main(int argc, char **argv) fix_scc(scc,ssb_bitmap); - fill_default_secondaryCellGroup(scc, - secondaryCellGroup, - 0, - 1, - n_tx, - 0); + prepare_scd(scd); + fill_default_secondaryCellGroup(scc, + scd, + secondaryCellGroup, + 0, + 1, + n_tx, + 0); + + /* RRC parameter validation for secondaryCellGroup */ + fix_scd(scd); /* -U option modify DMRS */ if(modify_dmrs) { update_dmrs_config(secondaryCellGroup, NULL,dmrs_arg); @@ -1114,7 +1135,9 @@ int main(int argc, char **argv) if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round; } // noise trials + blerStats[snrRun] = (float) n_errors / (float) n_trials; roundStats[snrRun]/=((float)n_trials); + berStats[snrRun] = (double)errors_scrambling/available_bits/n_trials; effRate /= n_trials; printf("*****************************************\n"); printf("SNR %f, (false positive %f)\n", SNR, @@ -1122,7 +1145,7 @@ int main(int argc, char **argv) printf("*****************************************\n"); printf("\n"); dump_pdsch_stats(gNB); - printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS); + printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, BLER %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],berStats[snrRun],blerStats[snrRun],effRate,effRate/TBS*100,TBS); printf("\n"); if (print_perf==1) { @@ -1187,15 +1210,19 @@ int main(int argc, char **argv) break; } - //if ((float)n_errors/(float)n_trials <= target_error_rate) { if (effRate > (eff_tp_check*TBS)) { printf("PDSCH test OK\n"); break; } + snrStats[snrRun] = SNR; snrRun++; } // NSR + LOG_M("dlsimStats.m","SNR",snrStats,snrRun,1,7); + LOG_MM("dlsimStats.m","BLER",blerStats,snrRun,1,7); + LOG_MM("dlsimStats.m","BER",berStats,snrRun,1,7); + LOG_MM("dlsimStats.m","rounds",roundStats,snrRun,1,7); /*if (n_trials>1) { printf("HARQ stats:\nSNR\tRounds\n"); psnr = snr0; diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index 8004fbb6b5..b78b42db91 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -55,19 +55,6 @@ signed char quantize(double D, double x, unsigned char B) { return ((char) qxd); } - -int8_t -mac_rrc_data_req_ue( - const module_id_t Mod_idP, - const int CC_id, - const frame_t frameP, - const rb_id_t Srb_id, - const uint8_t Nb_tb, - uint8_t *const buffer_pP, - const mac_enb_index_t eNB_indexP, - const uint8_t mbsfn_sync_area - ) { return(0);} - int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {return(0);} //NR_IF_Module_t *NR_IF_Module_init(int Mod_id){return(NULL);} int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } @@ -235,6 +222,7 @@ void fill_scc(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap); void prepare_scc(NR_ServingCellConfigCommon_t *scc); +void prepare_scd(NR_ServingCellConfig_t *scd); ngap_gNB_config_t ngap_config; uint32_t ngap_generate_gNB_id(void) {return 0;} void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { return;} diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 2512988371..a3c2501197 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -101,8 +101,8 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, //gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED; gNB->mac_enabled = 1; - fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); - fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->dl_CarrierFreq = 3600000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 3600000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); if (mu>2) fp->nr_band = 257; else fp->nr_band = 78; fp->threequarter_fs= 0; @@ -111,7 +111,7 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, nr_init_frame_parms(gNB_config, fp); - init_symbol_rotation(fp,fp->dl_CarrierFreq); + init_symbol_rotation(fp); gNB->configured = 1; LOG_I(PHY,"gNB configured\n"); @@ -540,7 +540,7 @@ int main(int argc, char **argv) if (input_fd==NULL) { gNB->pbch_configured = 1; - gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0; + gNB->ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33; for (int slot=0;slotslots_per_frame;slot++) { for (aa=0; aaframe_parms.nb_antennas_tx; aa++) @@ -692,9 +692,7 @@ int main(int argc, char **argv) nr_slot_fep(UE, &proc, i%frame_parms->symbols_per_slot, - ssb_slot, - 0, - 0); + ssb_slot); nr_pbch_channel_estimation(UE,&proc,0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf); @@ -718,9 +716,9 @@ int main(int argc, char **argv) payload_ret = (UE->pbch_vars[0]->xtra_byte == gNB_xtra_byte); for (i=0;i<3;i++){ - payload_ret += (UE->pbch_vars[0]->decoded_output[i] == (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i))); + payload_ret += (UE->pbch_vars[0]->decoded_output[i] == ((gNB->ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff)); } - //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->rx_ind.rx_indication_body->mib_pdu.additional_bits); + //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte); //printf("ret %d\n", payload_ret); if (payload_ret!=4) n_errors_payload++; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index c90bcf1395..74ca8d9184 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -64,7 +64,7 @@ double cpuf; extern uint16_t prach_root_sequence_map0_3[838]; openair0_config_t openair0_cfg[MAX_CARDS]; //uint8_t nfapi_mode=0; -int sl_ahead = 0; +uint16_t sl_ahead = 0; //void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe); @@ -132,13 +132,24 @@ nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) {return 0;} -// Dummy function to avoid linking error at compilation of nr-prachsim -int is_x2ap_enabled(void) +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} + +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) { return 0; } -int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { +// Dummy function to avoid linking error at compilation of nr-prachsim +int is_x2ap_enabled(void) +{ return 0; } @@ -454,7 +465,10 @@ int main(int argc, char **argv){ nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions); - uint64_t absoluteFrequencyPointA = (mu==1 ? 640000 : 2070833); + uint64_t absoluteFrequencyPointA = to_nrarfcn(frame_parms->nr_band, + frame_parms->dl_CarrierFreq, + frame_parms->numerology_index, + frame_parms->N_RB_UL*(180e3)*(1 << frame_parms->numerology_index)); uint8_t subframe = slot/frame_parms->slots_per_subframe; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 443ee6e1c0..d8fef539ba 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -75,13 +75,14 @@ PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; -int sf_ahead=4 ; +uint16_t sf_ahead=4 ; int slot_ahead=6 ; -int sl_ahead=0; +uint16_t sl_ahead=0; double cpuf; //uint8_t nfapi_mode = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; +extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) { return 0; } @@ -155,15 +156,27 @@ int is_x2ap_enabled(void) return 0; } -//nFAPI P7 dummy functions +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) +{ + return; +} + +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, + const int CC_id, + const uint8_t gNB_id, + const frame_t frameP, + const rb_id_t Srb_id, + uint8_t *buffer_pP) +{ + return 0; +} + +//nFAPI P7 dummy functions int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } -int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { - return 0; -} int nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out) @@ -607,8 +620,8 @@ int main(int argc, char **argv) frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) - frame_parms->nb_antennas_tx = n_tx; - frame_parms->nb_antennas_rx = n_rx; + //frame_parms->nb_antennas_tx = n_tx; + //frame_parms->nb_antennas_rx = n_rx; frame_parms->N_RB_DL = N_RB_DL; frame_parms->N_RB_UL = N_RB_UL; frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL; @@ -626,6 +639,7 @@ int main(int argc, char **argv) rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon)); NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon; + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup)); prepare_scc(rrc.carrier.servingcellconfigcommon); uint64_t ssb_bitmap; @@ -633,7 +647,10 @@ int main(int argc, char **argv) fix_scc(scc,ssb_bitmap); + prepare_scd(scd); + fill_default_secondaryCellGroup(scc, + scd, secondaryCellGroup, 0, 1, @@ -642,11 +659,14 @@ int main(int argc, char **argv) // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); + /* RRC parameter validation for secondaryCellGroup */ + fix_scd(scd); + AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface"); gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; // common configuration - rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL); + rrc_mac_config_req_gNB(0,0,n_rx,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL); // UE dedicated configuration rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); phy_init_nr_gNB(gNB,0,0); @@ -1053,70 +1073,69 @@ int main(int argc, char **argv) } - nr_fill_ulsch(gNB,frame,slot,pusch_pdu); + //nr_fill_ulsch(gNB,frame,slot,pusch_pdu); // Not needed as its its already filled as apart of "nr_schedule_response(Sched_INFO);" for (int i=0;i<(TBS/8);i++) ulsch_ue[0]->harq_processes[harq_pid]->a[i]=i&0xff; if (input_fd == NULL) { - // set FAPI parameters for UE, put them in the scheduled response and call - nr_ue_scheduled_response(&scheduled_response); - - - /////////////////////////phy_procedures_nr_ue_TX/////////////////////// - /////////// - - phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id); - - - if (n_trials==1) { - LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1); - LOG_M("txsig0F.m","txs0F", UE->common_vars.txdataF[0],frame_parms->ofdm_symbol_size*14,1,1); - } - /////////// - //////////////////////////////////////////////////// - tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); - - txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], - frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); + // set FAPI parameters for UE, put them in the scheduled response and call + nr_ue_scheduled_response(&scheduled_response); + + + /////////////////////////phy_procedures_nr_ue_TX/////////////////////// + /////////// + + phy_procedures_nrUE_TX(UE, &UE_proc, gNB_id); + + + if (n_trials==1) { + LOG_M("txsig0.m","txs0", UE->common_vars.txdata[0],frame_parms->samples_per_subframe*10,1,1); + LOG_M("txsig0F.m","txs0F", UE->common_vars.txdataF[0],frame_parms->ofdm_symbol_size*14,1,1); + } + /////////// + //////////////////////////////////////////////////// + tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); + + txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); } else n_trials = 1; if (input_fd == NULL ) { - sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;; - sigma = pow(10,sigma_dB/10); + sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;; + sigma = pow(10,sigma_dB/10); - if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double)frame_parms->ofdm_symbol_size/(12*nb_rb)); + if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double) + frame_parms->ofdm_symbol_size/(12*nb_rb)); - for (i=0; icommon_vars.txdata[aa][slot_offset]))[(i<<1)]); - s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]); - } - } - + for (i=0; inb_antennas_rx; aa++) { + s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)]); + s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][slot_offset]))[(i<<1)+1]); + } + } - if (UE2gNB->max_Doppler == 0) { - multipath_channel(UE2gNB,s_re,s_im,r_re,r_im, - slot_length,0,(n_trials==1)?1:0); - } else { - multipath_tv_channel(UE2gNB,s_re,s_im,r_re,r_im, - 2*slot_length,0); - } - for (i=0; inb_antennas_rx; ap++) { - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); + + if (UE2gNB->max_Doppler == 0) { + multipath_channel(UE2gNB, s_re, s_im, r_re, r_im, slot_length, 0, (n_trials==1)?1:0); + } else { + multipath_tv_channel(UE2gNB, s_re, s_im, r_re, r_im, 2*slot_length, 0); + } + for (i=0; inb_antennas_rx; ap++) { + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); /* Add phase noise if enabled */ if (pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { phase_noise(ts, &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)], &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1]); } - } - } + } + } - } + } /*End input_fd */ if(pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 02f878ee2e..87f926b206 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -42,6 +42,7 @@ #include "LTE_SL-DiscResourcePool-r12.h" #include "NR_RACH-ConfigCommon.h" #include "NR_ServingCellConfigCommon.h" +#include "NR_ServingCellConfig.h" //-------------------------------------------------------------------------------------------// // Messages for RRC logging #if defined(DISABLE_ITTI_XER_PRINT) @@ -405,6 +406,7 @@ typedef struct NRRrcConfigurationReq_s { uint16_t mnc[PLMN_LIST_MAX_SIZE]; uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; NR_ServingCellConfigCommon_t *scc; + NR_ServingCellConfig_t *scd; int ssb_SubcarrierOffset; int pdsch_AntennaPorts; int pusch_TargetSNRx10; diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h index bd0788d2d0..2151375686 100644 --- a/openair2/COMMON/s1ap_messages_types.h +++ b/openair2/COMMON/s1ap_messages_types.h @@ -398,6 +398,11 @@ typedef struct s1ap_register_enb_req_s { /* Number of SCTP streams used for a mme association */ uint16_t sctp_in_streams; uint16_t sctp_out_streams; + uint16_t s1_setuprsp_wait_timer; + uint16_t s1_setupreq_wait_timer; + uint16_t s1_setupreq_count; + uint16_t sctp_req_timer; + uint16_t sctp_req_count; } s1ap_register_enb_req_t; //-------------------------------------------------------------------------------------------// diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 6c709ea63b..d05fe7ac26 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2429,6 +2429,65 @@ int RCconfig_S1( "to\n" " tracking_area_code = 1; // no string!!\n" " plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n"); + if(*ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_rsp_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = 5; + } + + if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_req_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = 5; + } + + if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_req_count value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = 0xffff; + } + + if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "sctp_req_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = 180; + } + + if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr; + } + else + { + LOG_E(S1AP, + "sctp_req_count value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = 0xffff; + } config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix); if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) { diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index de7e0bbdad..f26863414c 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -214,6 +214,11 @@ typedef enum { #define ENB_CONFIG_STRING_X2 "enable_x2" #define ENB_CONFIG_STRING_ENB_M2 "enable_enb_m2" #define ENB_CONFIG_STRING_MCE_M2 "enable_mce_m2" +#define ENB_CONFIG_STRING_S1SETUP_RSP_TIMER "s1setup_rsp_timer" +#define ENB_CONFIG_STRING_S1SETUP_REQ_TIMER "s1setup_req_timer" +#define ENB_CONFIG_STRING_S1SETUP_REQ_COUNT "s1setup_req_count" +#define ENB_CONFIG_STRING_SCTP_REQ_TIMER "sctp_req_timer" +#define ENB_CONFIG_STRING_SCTP_REQ_COUNT "sctp_req_count" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -239,6 +244,11 @@ typedef enum { {ENB_CONFIG_STRING_X2, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_MCE_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_RSP_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_SCTP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:180, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_SCTP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \ } #define ENB_ENB_ID_IDX 0 @@ -261,6 +271,11 @@ typedef enum { #define ENB_ENABLE_X2 17 #define ENB_ENABLE_ENB_M2 18 #define ENB_ENABLE_MCE_M2 19 +#define ENB_S1SETUP_RSP_TIMER_IDX 20 +#define ENB_S1SETUP_REQ_TIMER_IDX 21 +#define ENB_S1SETUP_REQ_COUNT_IDX 22 +#define ENB_SCTP_REQ_TIMER_IDX 23 +#define ENB_SCTP_REQ_COUNT_IDX 24 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define ENBPARAMS_CHECK { \ diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index 1f1d076e9d..d05908e8ed 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -211,6 +211,24 @@ #define CARRIERBANDWIDTH_OKVALUES {11,18,24,25,31,32,38,51,52,65,66,78,79,93,106,107,121,132,133,135,160,162,189,216,217,245,264,270,273} +/* Serving Cell Config Dedicated */ +#define GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED "servingCellConfigDedicated" +#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0 "dl_ptrsFreqDensity0_0" +#define GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0 "dl_ptrsFreqDensity1_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0 "dl_ptrsTimeDensity0_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0 "dl_ptrsTimeDensity1_0" +#define GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0 "dl_ptrsTimeDensity2_0" +#define GNB_CONFIG_STRING_DLPTRSEPRERATIO_0 "dl_ptrsEpreRatio_0" +#define GNB_CONFIG_STRING_DLPTRSREOFFSET_0 "dl_ptrsReOffset_0" +#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0 "ul_ptrsFreqDensity0_0" +#define GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0 "ul_ptrsFreqDensity1_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0 "ul_ptrsTimeDensity0_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0 "ul_ptrsTimeDensity1_0" +#define GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0 "ul_ptrsTimeDensity2_0" +#define GNB_CONFIG_STRING_ULPTRSREOFFSET_0 "ul_ptrsReOffset_0" +#define GNB_CONFIG_STRING_ULPTRSMAXPORTS_0 "ul_ptrsMaxPorts_0" +#define GNB_CONFIG_STRING_ULPTRSPOWER_0 "ul_ptrsPower_0" + /*--------------------------------------------------------------------------------------------------------------------*/ /* pdcch_ConfigSIB1 parameters */ /*--------------------------------------------------------------------------------------------------------------------*/ @@ -395,6 +413,26 @@ {GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,i64ptr:&scc->ss_PBCH_BlockPower,defint64val:20,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,i64ptr:scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,defintval:-1,TYPE_INT64,0}} +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* Serving Cell Config Dedicated configuration parameters */ +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + +#define SCDPARAMS_DESC(scd) { \ +{GNB_CONFIG_STRING_DLPTRSFREQDENSITY0_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSFREQDENSITY1_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY0_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY1_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSTIMEDENSITY2_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[2],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSEPRERATIO_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio,defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_DLPTRSREOFFSET_0,NULL,0,i64ptr:scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset,defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSFREQDENSITY0_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSFREQDENSITY1_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY0_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[0],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY1_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[1],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSTIMEDENSITY2_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[2],defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSREOFFSET_0,NULL,0,i64ptr:scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset,defint64val:-1,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSMAXPORTS_0,NULL,0,i64ptr:&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->maxNrofPorts,defint64val:0,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULPTRSPOWER_0,NULL,0,i64ptr:&scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->ptrs_Power,defint64val:0,TYPE_INT64,0}} diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 957485a992..608827cc7a 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -293,6 +293,171 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { } } +/* Function to allocate dedicated serving cell config strutures */ +void prepare_scd(NR_ServingCellConfig_t *scd) { + // Allocate downlink structures + + scd->downlinkBWP_ToAddModList = CALLOC(1, sizeof(scd->downlinkBWP_ToAddModList)); + + // Downlink bandwidth part + NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); + bwp->bwp_Id = 1; + + // Allocate downlink dedicated bandwidth part and PDSCH structures + bwp->bwp_Dedicated = calloc(1, sizeof(*bwp->bwp_Dedicated)); + bwp->bwp_Dedicated->pdsch_Config = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config)); + bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; + bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; + + // Allocate DL DMRS and PTRS configuration + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + NR_DMRS_DownlinkConfig_t *NR_DMRS_DownlinkCfg = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; + NR_DMRS_DownlinkCfg->phaseTrackingRS=CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS)); + NR_DMRS_DownlinkCfg->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup; + NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup)); + NR_PTRS_DownlinkConfig_t *NR_PTRS_DownlinkCfg = NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup; + NR_PTRS_DownlinkCfg->frequencyDensity = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->frequencyDensity)); + int *dl_rbs[2]; + for (int i=0;i<2;i++) { + dl_rbs[i] = CALLOC(1, sizeof(*dl_rbs[i])); + *dl_rbs[i] = 0; + ASN_SEQUENCE_ADD(&NR_PTRS_DownlinkCfg->frequencyDensity->list, dl_rbs[i]); + } + NR_PTRS_DownlinkCfg->timeDensity = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->timeDensity)); + int *dl_mcs[3]; + for (int i=0;i<3;i++) { + dl_mcs[i] = CALLOC(1, sizeof(*dl_mcs[i])); + *dl_mcs[i] = 0; + ASN_SEQUENCE_ADD(&NR_PTRS_DownlinkCfg->timeDensity->list, dl_mcs[i]); + } + NR_PTRS_DownlinkCfg->epre_Ratio = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->epre_Ratio)); + NR_PTRS_DownlinkCfg->resourceElementOffset = CALLOC(1, sizeof(NR_PTRS_DownlinkCfg->resourceElementOffset)); + *NR_PTRS_DownlinkCfg->resourceElementOffset = 0; + ASN_SEQUENCE_ADD(&scd->downlinkBWP_ToAddModList->list,bwp); + + // Allocate uplink structures + + scd->uplinkConfig = CALLOC(1, sizeof(NR_UplinkConfig_t)); + scd->uplinkConfig->uplinkBWP_ToAddModList = CALLOC(1, sizeof(scd->uplinkConfig->uplinkBWP_ToAddModList)); + + NR_PUSCH_Config_t *pusch_Config = CALLOC(1, sizeof(*pusch_Config)); + + // Allocate UL DMRS and PTRS structures + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + NR_DMRS_UplinkConfig->phaseTrackingRS = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS)); + NR_DMRS_UplinkConfig->phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup; + NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup)); + NR_PTRS_UplinkConfig_t *NR_PTRS_UplinkConfig = NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup; + NR_PTRS_UplinkConfig->transformPrecoderDisabled = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled)); + NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity)); + int *n_rbs[2]; + for (int i=0;i<2;i++) { + n_rbs[i] = CALLOC(1, sizeof(*n_rbs[i])); + *n_rbs[i] = 0; + ASN_SEQUENCE_ADD(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity->list, n_rbs[i]); + } + NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity)); + int *ptrs_mcs[3]; + for (int i = 0; i < 3; i++) { + ptrs_mcs[i] = CALLOC(1, sizeof(*ptrs_mcs[i])); + *ptrs_mcs[i] = 0; + ASN_SEQUENCE_ADD(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity->list, ptrs_mcs[i]); + } + NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = CALLOC(1, sizeof(NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset)); + *NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = 0; + + // UL bandwidth part + NR_BWP_Uplink_t *ubwp = CALLOC(1, sizeof(*ubwp)); + ubwp->bwp_Id = 1; + ubwp->bwp_Dedicated = CALLOC(1, sizeof(*ubwp->bwp_Dedicated)); + + ubwp->bwp_Dedicated->pusch_Config = CALLOC(1, sizeof(*ubwp->bwp_Dedicated->pusch_Config)); + ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; + ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config; + + ASN_SEQUENCE_ADD(&scd->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); +} + +/* This function checks dedicated serving cell configuration and performs fixes as needed */ +void fix_scd(NR_ServingCellConfig_t *scd) { + // Check for DL PTRS parameters validity + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) { + // If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present + for (int i = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.count-1; i >= 0; i--) { + if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] < 1) + || (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] > 276)) { + LOG_I(RRC, "DL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) { + // If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present + for (int i = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.count-1; i >= 0; i--) { + if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] < 0) + || (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] > 29)) { + LOG_I(RRC, "DL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) { + if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset > 2) { + LOG_I(RRC, "Freeing DL PTRS resourceElementOffset \n"); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = NULL; + } + if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio > 1) { + LOG_I(RRC, "Freeing DL PTRS epre_Ratio \n"); + free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio); + scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = NULL; + } + } + + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { + // If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present + for (int i = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.count-1; i >= 0; i--) { + if ((*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] < 1) + || (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] > 276)) { + LOG_I(RRC, "UL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { + // If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present + for (int i = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.count-1; i >= 0; i--) { + if ((*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] < 0) + || (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] > 29)) { + LOG_I(RRC, "UL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL; + break; + } + } + } + if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) { + // Check for UL PTRS parameters validity + if (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset > 2) { + LOG_I(RRC, "Freeing UL PTRS resourceElementOffset \n"); + free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset); + scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset = NULL; + } + } +} + void RCconfig_nr_flexran() { uint16_t i; @@ -627,6 +792,13 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { prepare_scc(scc); paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc); paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0}; + + // Serving Cell Config Dedicated + NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t)); + memset((void*)scd,0,sizeof(NR_ServingCellConfig_t)); + prepare_scd(scd); + paramdef_t SCDsParams[] = SCDPARAMS_DESC(scd); + paramlist_def_t SCDsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, NULL, 0}; ////////// Physical parameters @@ -700,6 +872,23 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { (int)scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower); fix_scc(scc,ssb_bitmap); } + + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + + config_getlist(&SCDsParamList, NULL, 0, aprefix); + if (SCDsParamList.numelt > 0) { + sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 0); + config_get( SCDsParams,sizeof(SCDsParams)/sizeof(paramdef_t),aprefix); + LOG_I(RRC,"Read in ServingCellConfigDedicated UL (FreqDensity_0 %d, FreqDensity_1 %d, TimeDensity_0 %d, TimeDensity_1 %d, TimeDensity_2 %d, RE offset %d \n", + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[0], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[1], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[0], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[1], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[2], + (int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset); + } + fix_scd(scd); + printf("NRRRC %d: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr)); if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) { @@ -770,6 +959,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { printf("pucch_TargetSNRx10 %d\n",*GNBParamList.paramarray[i][GNB_PUCCH_TARGETPOW_X10_IDX].iptr); NRRRC_CONFIGURATION_REQ (msg_p).pucch_TargetSNRx10 = *GNBParamList.paramarray[i][GNB_PUCCH_TARGETPOW_X10_IDX].iptr; NRRRC_CONFIGURATION_REQ (msg_p).scc = scc; + NRRRC_CONFIGURATION_REQ (msg_p).scd = scd; }// diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 1bae590a59..ae8522bc83 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -490,7 +490,7 @@ typedef struct { /*! \brief Uplink SCH PDU Structure */ typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ + uint8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ uint16_t Pdu_size; } __attribute__ ((__packed__)) ULSCH_PDU; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 5d1b08bcf6..cdeb23c099 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -31,6 +31,7 @@ */ #include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include "common/utils/nr/nr_common.h" #include #define reserved 0xffff @@ -1220,6 +1221,11 @@ int get_nr_prach_occasion_info_from_index(uint8_t index, else { // FDD x = table_6_3_3_2_2_prachConfig_Index[index][2]; s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; + for(int i = 0; i < 64 ; i++) { + if ( (s_map >> i) & 0x01) { + (*N_RA_sfn)++; + } + } *N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; @@ -1396,19 +1402,17 @@ int get_nr_prach_info_from_index(uint8_t index, if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n", - frame, - slot, - index, - table_6_3_3_2_3_prachConfig_Index[index][6], - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur, - *N_RA_slot, - *RA_sfn_index); + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n", frame, + slot, + index, table_6_3_3_2_3_prachConfig_Index[index][6], + pointa, + mu, + unpaired, + *start_symbol, + *N_t_slot, + *N_dur, + *N_RA_slot, + *RA_sfn_index); } return 1; } @@ -1429,6 +1433,11 @@ int get_nr_prach_info_from_index(uint8_t index, if ( (table_6_3_3_2_2_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) return 0; // no prach in even slots @ 30kHz for 1 prach per subframe } + for(int i = 0; i <= subframe ; i++) { + if ( (s_map >> i) & 0x01) { + (*RA_sfn_index)++; + } + } if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; @@ -1567,79 +1576,6 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, } } -// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) -// Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) -// Notes: -// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL -// - Frequencies are expressed in KHz -// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster -nr_bandentry_t nr_bandtable[] = { - {1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, - {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, - {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, - {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, - {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, - {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, - {12, 698000, 716000, 729000, 746000, 20, 145800, 100}, - {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, - {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, - {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, - {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, - {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, - {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, - {29, 000, 000, 717000, 728000, 20, 143400, 100}, - {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, - {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, - {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, - {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, - {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, - {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, - //{48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, - //{48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, - {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, - {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, - {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, - {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, - {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, - {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, - {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, - {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, - {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, - {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, - {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, - {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, - {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, - {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, - {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, - {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, - {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {81, 880000, 915000, 000, 000, 20, 176000, 100}, - {82, 832000, 862000, 000, 000, 20, 166400, 100}, - {83, 703000, 748000, 000, 000, 20, 140600, 100}, - {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, - {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {89, 824000, 849000, 000, 000, 20, 342000, 100}, - {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, - {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, - {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, - {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, - {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, - {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, - {257,26500020,29500000,26500020,29500000, 1,2054166, 60}, - {257,26500080,29500000,26500080,29500000, 2,2054167, 120}, - {258,24250080,27500000,24250080,27500000, 1,2016667, 60}, - {258,24250080,27500000,24250080,27500000, 2,2016667, 120}, - {260,37000020,40000000,37000020,40000000, 1,2229166, 60}, - {260,37000080,40000000,37000080,40000000, 2,2229167, 120}, - {261,27500040,28350000,27500040,28350000, 1,2070833, 60}, - {261,27500040,28350000,27500040,28350000, 2,2070833, 120} -}; - - // TS 38.211 Table 6.4.1.1.3-3: PUSCH DMRS positions l' within a slot for single-symbol DMRS and intra-slot frequency hopping disabled. // The first 4 colomns are PUSCH mapping type A and the last 4 colomns are PUSCH mapping type B. // When l' = l0, it is represented by 1 @@ -1680,11 +1616,9 @@ int32_t table_6_4_1_1_3_4_pusch_dmrs_positions_l [12][8] = { {1, 1025, -1, -1, 1, 513, -1, -1}, //14 // (DMRS l' position) }; -#define NR_BANDTABLE_SIZE (sizeof(nr_bandtable)/sizeof(nr_bandentry_t)) - // Returns the corresponding row index of the NR table -int get_nr_table_idx(int nr_bandP, uint8_t scs_index){ - +int get_nr_table_idx(int nr_bandP, uint8_t scs_index) +{ int i, j; int scs_khz = 15 << scs_index; int supplementary_bands[] = {29,75,76,80,81,82,83,84,86,89,95}; @@ -1695,8 +1629,8 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index){ AssertFatal(0 == 1, "Band %d is a supplementary band (%d). This is not supported yet.\n", nr_bandP, supplementary_bands[j]); } - AssertFatal(nr_bandP <= nr_bandtable[NR_BANDTABLE_SIZE-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[NR_BANDTABLE_SIZE-1].band); - for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++); + AssertFatal(nr_bandP <= nr_bandtable[nr_bandtable_size-1].band, "NR band %d exceeds NR bands table maximum limit %d\n", nr_bandP, nr_bandtable[nr_bandtable_size-1].band); + for (i = 0; i < nr_bandtable_size && nr_bandtable[i].band != nr_bandP; i++); // selection of correct Deltaf raster according to SCS if ((nr_bandtable[i].deltaf_raster != 100) && (nr_bandtable[i].deltaf_raster != scs_khz)) @@ -1705,35 +1639,33 @@ int get_nr_table_idx(int nr_bandP, uint8_t scs_index){ LOG_D(PHY, "NR band table index %d (Band %d, dl_min %lu, ul_min %lu)\n", i, nr_bandtable[i].band, nr_bandtable[i].dl_min,nr_bandtable[i].ul_min); return i; - } // Computes the duplex spacing (either positive or negative) in KHz -void get_delta_duplex(int nr_bandP, uint8_t scs_index, int32_t *delta_duplex){ - +int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index) +{ int nr_table_idx = get_nr_table_idx(nr_bandP, scs_index); - *delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min); + int32_t delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min); - LOG_D(PHY, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", *delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band); + LOG_I(PHY, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band); + return delta_duplex; } -void get_frame_type(uint16_t current_band, - uint8_t scs_index, - lte_frame_type_t *current_type){ +lte_frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index) +{ + lte_frame_type_t current_type; + int32_t delta_duplex = get_delta_duplex(current_band, scs_index); - int32_t current_offset; - get_delta_duplex(current_band, scs_index, ¤t_offset); - - current_offset *= 1000; - if (current_offset == 0) - *current_type = TDD; + if (delta_duplex == 0) + current_type = TDD; else - *current_type = FDD; + current_type = FDD; - LOG_I(MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[*current_type], current_offset); + LOG_I(MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex); + return current_type; } uint16_t config_bandwidth(int mu, int nb_rb, int nr_band) @@ -1911,7 +1843,6 @@ uint64_t from_nrarfcn(int nr_bandP, int deltaFglobal = 5; uint32_t N_REF_Offs = 0; uint64_t F_REF_Offs_khz = 0; - int32_t delta_duplex; uint64_t N_OFFs, frequency, freq_min; int i = get_nr_table_idx(nr_bandP, scs_index); @@ -1926,7 +1857,7 @@ uint64_t from_nrarfcn(int nr_bandP, F_REF_Offs_khz = 24250080; } - get_delta_duplex(nr_bandP, scs_index, &delta_duplex); + int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index); if (delta_duplex <= 0){ // DL band >= UL band if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL @@ -2836,11 +2767,15 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) { else return(slot_in_period <= slots1+scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); } -int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) { +int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slot, lte_frame_type_t frame_type) { int period,period1,period2=0; - if (scc->tdd_UL_DL_ConfigurationCommon==NULL) return(1); + // Note: condition on frame_type + // goal: the UL scheduler assumes mode is TDD therefore this hack is needed to make FDD work + if (scc->tdd_UL_DL_ConfigurationCommon == NULL || frame_type == FDD) { + return(1); + } if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 && scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530) @@ -3064,51 +2999,14 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, valid = false; return valid; } - //printf("[MAC] PTRS is set K= %u L= %u\n", *K_ptrs,1<<*L_ptrs); + + /* Moved below check from scheduler function to here */ + if (*L_ptrs >= NrOfSymbols) { + valid = false; + return valid; + } return valid; } -void get_band(uint64_t downlink_frequency, - uint16_t *current_band, - int32_t *current_offset, - lte_frame_type_t *current_type) -{ - int ind; - uint64_t center_frequency_khz; - uint64_t center_freq_diff_khz; - uint64_t dl_freq_khz = downlink_frequency/1000; - - center_freq_diff_khz = 999999999999999999; // 2^64 - *current_band = 0; - - for ( ind=0; - ind < sizeof(nr_bandtable) / sizeof(nr_bandtable[0]); - ind++) { - - LOG_I(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min,nr_bandtable[ind].ul_min); - - if ( nr_bandtable[ind].dl_min <= dl_freq_khz && nr_bandtable[ind].dl_max >= dl_freq_khz ) { - - center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min)/2; - if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ - *current_band = nr_bandtable[ind].band; - *current_offset = (nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min)*1000; - center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); - - if (*current_offset == 0) - *current_type = TDD; - else - *current_type = FDD; - } - } - } - - LOG_I( PHY, "DL frequency %"PRIu64": band %d, frame_type %d, UL frequency %"PRIu64"\n", - downlink_frequency, *current_band, *current_type, downlink_frequency+*current_offset); - - AssertFatal(*current_band != 0, - "Can't find EUTRA band for frequency %lu\n", downlink_frequency); -} - uint32_t get_ssb_slot(uint32_t ssb_index){ // this function now only support f <= 3GHz @@ -3480,3 +3378,79 @@ int get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDC return 0; } + +/* extract UL PTRS values from RRC and validate it based upon 38.214 6.2.3 */ +bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, + uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs, + uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower, + uint8_t NrOfSymbols) +{ + bool valid = true; + + /* as defined in T 38.214 6.2.3 */ + if(rbSize < 3) { + valid = false; + return valid; + } + /* Check for Frequency Density values */ + if(ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.count < 2) { + /* Default value for K_PTRS = 2 as defined in T 38.214 6.2.3 */ + *K_ptrs = 2; + } + else { + *K_ptrs = get_K_ptrs(*ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[0], + *ul_ptrs_config->transformPrecoderDisabled->frequencyDensity->list.array[1], + rbSize); + } + /* Check for time Density values */ + if(ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.count < 3) { + *L_ptrs = 0; + } + else { + *L_ptrs = get_L_ptrs(*ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[0], + *ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[1], + *ul_ptrs_config->transformPrecoderDisabled->timeDensity->list.array[2], + mcsIndex, + mcsTable); + } + + *reOffset = *ul_ptrs_config->transformPrecoderDisabled->resourceElementOffset; + *maxNumPorts = ul_ptrs_config->transformPrecoderDisabled->maxNrofPorts; + *ulPower = ul_ptrs_config->transformPrecoderDisabled->ptrs_Power; + /* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table + * 6.2.3.1-1 and Table 6.2.3.1-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present + */ + if(*K_ptrs ==2 || *K_ptrs ==4 ) { + valid = true; + } + else { + valid = false; + return valid; + } + if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2 ) { + valid = true; + } + else { + valid = false; + return valid; + } + /* PTRS is not present also : + * When the UE is receiving a PUSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume + * PT-RS is not transmitted + * When the UE is receiving a PUSCH with allocation duration of 2 symbols as defined in Clause 6.4.1.2.2 of [4, TS + * 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted. + */ + if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) { + valid = false; + return valid; + } + + /* Moved below check from nr_ue_scheduler function to here */ + if (*L_ptrs >= NrOfSymbols) { + valid = false; + return valid; + } + return valid; +} + diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 087d316567..3e21131b69 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -39,9 +39,9 @@ uint16_t config_bandwidth(int mu, int nb_rb, int nr_band); -void get_frame_type(uint16_t nr_bandP, uint8_t scs_index, lte_frame_type_t *current_type); +lte_frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index); -void get_delta_duplex(int nr_bandP, uint8_t scs_index, int32_t *delta_duplex); +int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index); uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); @@ -51,7 +51,7 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); -int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); +int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc, slot_t slotP, lte_frame_type_t frame_type); uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc, const NR_CellGroupConfig_t *secondaryCellGroup, @@ -81,7 +81,7 @@ int get_nr_prach_info_from_index(uint8_t index, uint8_t *N_dur, uint16_t *RA_sfn_index, uint8_t *N_RA_slot, - uint8_t *config_period); + uint8_t *config_period); int get_nr_prach_occasion_info_from_index(uint8_t index, uint32_t pointa, @@ -140,8 +140,12 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex, uint8_t *nERatio,uint8_t *reOffset, uint8_t NrOfSymbols); -void get_band(uint64_t downlink_frequency, uint16_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type); +bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config, + uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs, + uint8_t *reOffset, uint8_t *maxNumPorts, uint8_t *ulPower, + uint8_t NrOfSymbols); uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols); /* \brief Set the transform precoding according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16 diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index f6bd5436bc..fee2efc4a8 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -203,13 +203,12 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; frequency_range_t frequency_range = band<100?FR1:FR2; - lte_frame_type_t frame_type; - get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type); + mac->frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); // cell config cfg->cell_config.phy_cell_id = *scc->physCellId; - cfg->cell_config.frame_duplex_type = frame_type; + cfg->cell_config.frame_duplex_type = mac->frame_type; // SSB config cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; @@ -313,7 +312,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, cfg->prach_config.num_prach_fd_occasions_list[i].k1 = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart; cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; - cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, frame_type,frequency_range); + cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, mac->frame_type, frequency_range); //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ??? } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index dd0aa15c52..3e299d291e 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -325,6 +325,8 @@ typedef struct { NR_ControlResourceSet_t *coreset[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP]; NR_SearchSpace_t *SSpace[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP][FAPI_NR_MAX_SS_PER_CORESET]; + lte_frame_type_t frame_type; + /*BWP*/ // dedicated active DL BWP NR_BWP_Id_t DL_BWP_Id; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index c4909c1384..14d1ea63fb 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -56,14 +56,14 @@ int8_t nr_ue_decode_mib( void *pduP, uint16_t cell_id ); -/**\brief decode sib1 pdu in NR_UE, from if_module dl_ind +/**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind \param module_id module id \param cc_id component carrier id \param gNB_index gNB index \param sibs_mask sibs mask \param pduP pointer to pdu \param pdu_length length of pdu */ -int8_t nr_ue_decode_sib1(module_id_t module_id, +int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_vars.c b/openair2/LAYER2/NR_MAC_UE/mac_vars.c index ecabdb870c..383267090f 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_vars.c +++ b/openair2/LAYER2/NR_MAC_UE/mac_vars.c @@ -32,7 +32,7 @@ #include -const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC"}; +const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC", "NR_RNTI_SP_CSI", "NR_RNTI_SI"}; const char *dci_formats[]={"1_0", "1_1", "2_0", "2_1", "2_2", "2_3", "0_0", "0_1"}; // table_7_3_1_1_2_2_3_4_5 contains values for number of layers and precoding information for tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2 diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index b4b63e0064..8f234cb585 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -35,6 +35,7 @@ /* RRC */ #include "NR_RACH-ConfigCommon.h" +#include "RRC/NR_UE/rrc_proto.h" /* PHY */ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" @@ -514,7 +515,8 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, uint8_t sdu_lcids[NB_RB_MAX] = {0}; uint16_t sdu_lengths[NB_RB_MAX] = {0}; - int TBS_bytes = 848, header_length_total=0, num_sdus, offset, mac_ce_len; + int num_sdus = 0; + int offset = 0; // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side if (!prach_resources->init_msg1) { @@ -532,36 +534,27 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, LOG_D(MAC, "RA not active. Checking for data to transmit from upper layers...\n"); - payload = (uint8_t*) &mac->CCCH_pdu.payload; - mac_ce_len = 0; + uint8_t TBS_max = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); + payload = (uint8_t*) mac->CCCH_pdu.payload; + num_sdus = 1; post_padding = 1; + sdu_lcids[0] = lcid; - if (0){ - // initialisation by RRC - // CCCH PDU - // size_sdu = (uint16_t) mac_rrc_data_req_ue(mod_id, - // CC_id, - // frame, - // CCCH, - // 1, - // mac_sdus, - // gNB_id, - // 0); - LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu); - } else { - // fill ulsch_buffer with random data - for (int i = 0; i < TBS_bytes; i++){ - mac_sdus[i] = (unsigned char) (lrand48()&0xff); - } - //Sending SDUs with size 1 - //Initialize elements of sdu_lcids and sdu_lengths - sdu_lcids[0] = lcid; - sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len; - header_length_total += 2 + (sdu_lengths[0] >= 128); - size_sdu += sdu_lengths[0]; + // initialisation by RRC + + // TODO: To be removed after RA procedures fully implemented + if(get_softmodem_params()->do_ra) { + nr_rrc_ue_generate_RRCSetupRequest(mod_id,gNB_id); } + // CCCH PDU + size_sdu = (uint16_t) nr_mac_rrc_data_req_ue(mod_id, CC_id, gNB_id, frame, CCCH, mac_sdus); + + sdu_lengths[0] = size_sdu; + + LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu); + if (size_sdu > 0) { LOG_D(MAC, "[UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", mod_id, frame, nr_slot_tx); @@ -589,12 +582,27 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, post_padding, 0); + AssertFatal(TBS_max > offset, "Frequency resources are not enough for Msg3!\n"); + // Padding: fill remainder with 0 if (post_padding > 0){ - for (int j = 0; j < (TBS_bytes - offset); j++) - payload[offset + j] = 0; // mac_pdu[offset + j] = 0; + for (int j = 0; j < (TBS_max - offset); j++) + payload[offset + j] = 0; } - } + } + + LOG_D(MAC,"size_sdu = %i\n", size_sdu); + LOG_D(MAC,"offset = %i\n", offset); + for(int k = 0; k < TBS_max; k++) { + LOG_D(MAC,"(%i): %i\n", k, prach_resources->Msg3[k]); + } + + // Msg3 was initialized with TBS_max bytes because the RA_Msg3_size will only be known after + // receiving Msg2 (which contains the Msg3 resource reserve). + // Msg3 will be transmitted with RA_Msg3_size bytes, removing unnecessary 0s. + mac->ulsch_pdu.Pdu_size = TBS_max; + memcpy(mac->ulsch_pdu.payload, prach_resources->Msg3, TBS_max); + } else if (ra->RA_window_cnt != -1) { // RACH is active LOG_D(MAC, "In %s [%d.%d] RA is active: RA window count %d, RA backoff count %d\n", __FUNCTION__, frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 64067e9d60..cb104092f1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -154,13 +154,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id, return 0; } -int8_t nr_ue_decode_sib1(module_id_t module_id, - int cc_id, - unsigned int gNB_index, - uint32_t sibs_mask, - uint8_t *pduP, - uint32_t pdu_len) { - LOG_D(MAC, "Decode sib1\n"); +int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, + int cc_id, + unsigned int gNB_index, + uint32_t sibs_mask, + uint8_t *pduP, + uint32_t pdu_len) { + LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); return 0; } @@ -583,7 +583,6 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } } - break; } @@ -814,7 +813,17 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti; + + // FIXME: fix number of additional dmrs + if(pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition == NULL) + pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition=calloc(1,sizeof(*pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_1 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; + + dlsch_config_pdu_1_1->BWPSize = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_1->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_1->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; + /* IDENTIFIER_DCI_FORMATS */ /* CARRIER_IND */ /* BANDWIDTH_PART_IND */ @@ -1010,6 +1019,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr &dlsch_config_pdu_1_1->PTRSReOffset, dlsch_config_pdu_1_1->number_symbols); if(valid_ptrs_setup==true) { dlsch_config_pdu_1_1->pduBitmap |= 0x1; + LOG_D(MAC, "DL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", dlsch_config_pdu_1_1->PTRSTimeDensity, dlsch_config_pdu_1_1->PTRSFreqDensity); } } @@ -2230,7 +2240,7 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t // TA command ul_time_alignment->apply_ta = 1; - ul_time_alignment->ta_command = rar->TA2 + (rar->TA1 << 5); + ul_time_alignment->ta_command = 31 + rar->TA2 + (rar->TA1 << 5); #ifdef DEBUG_RAR // CSI diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index d6e1cba6df..ad1958ef33 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -118,13 +118,14 @@ long get_k2(NR_UE_MAC_INST_t *mac, uint8_t time_domain_ind) { * This function returns the UL config corresponding to a given UL slot * from MAC instance . */ -fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) { +fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) +{ //Check if request to access ul_config is for a UL slot - if (is_nr_UL_slot(mac->scc, slot) == 0) { + if (is_nr_UL_slot(mac->scc, slot, mac->frame_type) == 0) { LOG_W(MAC, "Slot %d is not a UL slot. %s called for wrong slot!!!\n", slot, __FUNCTION__); return NULL; } - + // Calculate the index of the UL slot in mac->ul_config_request list. This is // based on the TDD pattern (slot configuration period) and number of UL+mixed // slots in the period. TS 38.213 Sec 11.1 @@ -560,20 +561,11 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } else if (dci) { int target_ss; - uint8_t ptrs_time_density; - uint8_t ptrs_freq_density; - nfapi_nr_ue_ptrs_ports_t ptrs_ports_list; + bool valid_ptrs_setup = 0; uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated; NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; - // These should come from RRC config!!! - uint8_t ptrs_mcs1 = 2; - uint8_t ptrs_mcs2 = 4; - uint8_t ptrs_mcs3 = 10; - uint16_t n_rb0 = 25; - uint16_t n_rb1 = 75; - // Basic sanity check for MCS value to check for a false or erroneous DCI if (dci->mcs > 28) { LOG_W(MAC, "MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", dci->mcs); @@ -689,12 +681,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->absolute_delta_PUSCH = 4; } - ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); - ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_config_pdu->rb_size); - // PTRS ports configuration - // TbD: ptrs_dmrs_port and ptrs_port_index are not initialised! - ptrs_ports_list.ptrs_re_offset = 0; - /* DMRS */ l_prime_mask = get_l_prime(pusch_config_pdu->nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) @@ -708,12 +694,20 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } /* PTRS */ - pusch_config_pdu->pusch_ptrs.ptrs_time_density = ptrs_time_density; - pusch_config_pdu->pusch_ptrs.ptrs_freq_density = ptrs_freq_density; - pusch_config_pdu->pusch_ptrs.ptrs_ports_list = &ptrs_ports_list; - - if (1 << pusch_config_pdu->pusch_ptrs.ptrs_time_density >= pusch_config_pdu->nr_of_symbols) { - pusch_config_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + if (mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS != NULL) { + if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) { + nfapi_nr_ue_ptrs_ports_t ptrs_ports_list; + pusch_config_pdu->pusch_ptrs.ptrs_ports_list = &ptrs_ports_list; + valid_ptrs_setup = set_ul_ptrs_values(mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup, + pusch_config_pdu->rb_size, pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table, + &pusch_config_pdu->pusch_ptrs.ptrs_freq_density,&pusch_config_pdu->pusch_ptrs.ptrs_time_density, + &pusch_config_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_config_pdu->pusch_ptrs.num_ptrs_ports, + &pusch_config_pdu->pusch_ptrs.ul_ptrs_power, pusch_config_pdu->nr_of_symbols); + if(valid_ptrs_setup==true) { + pusch_config_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; + } + LOG_D(MAC, "UL PTRS values: PTRS time den: %d, PTRS freq den: %d\n", pusch_config_pdu->pusch_ptrs.ptrs_time_density, pusch_config_pdu->pusch_ptrs.ptrs_freq_density); + } } } @@ -889,34 +883,40 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size; - // Push data from MAC to PHY only when NDI toggles - if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){ - // Getting IP traffic to be transmitted - data_existing = nr_ue_get_sdu(mod_id, - cc_id, - frame_tx, - slot_tx, - 0, - ulsch_input_buffer, - TBS_bytes, - &access_mode); - } + if (ra->ra_state == WAIT_RAR){ + memcpy(ulsch_input_buffer, mac->ulsch_pdu.payload, TBS_bytes); + LOG_D(NR_MAC,"[RAPROC] Msg3 to be transmitted:\n"); + for (int k = 0; k < TBS_bytes; k++) { + LOG_D(NR_MAC,"(%i): 0x%x\n",k,mac->ulsch_pdu.payload[k]); + } + } else { + if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){ + // Getting IP traffic to be transmitted + data_existing = nr_ue_get_sdu(mod_id, + cc_id, + frame_tx, + slot_tx, + 0, + ulsch_input_buffer, + TBS_bytes, + &access_mode); + } - mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; - //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity - if (!IS_SOFTMODEM_NOS1 || !data_existing) { - //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid - //and block this traffic from being forwarded to the upper layers at the gNB - LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes); + mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; + //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity + if (!IS_SOFTMODEM_NOS1 || !data_existing) { + //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid + //and block this traffic from being forwarded to the upper layers at the gNB + LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes); - //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) - //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should - //have a valid LCID (nr_process_mac_pdu function) - ulsch_input_buffer[0] = 0x31; + //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) + //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should + //have a valid LCID (nr_process_mac_pdu function) + ulsch_input_buffer[0] = 0x31; - for (int i = 1; i < TBS_bytes; i++) { - ulsch_input_buffer[i] = (unsigned char) rand(); - //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); + for (int i = 1; i < TBS_bytes; i++) { + ulsch_input_buffer[i] = (unsigned char) rand(); + } } } @@ -1662,7 +1662,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s ra->RA_offset = 2; // to compensate the rx frame offset at the gNB ra->generate_nr_prach = 0; // Reset flag for PRACH generation - if (is_nr_UL_slot(scc, slotP)) { + if (is_nr_UL_slot(scc, slotP, mac->frame_type)) { // WIP Need to get the proper selected ssb_idx // Initial beam selection functionality is not available yet @@ -1683,13 +1683,11 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s format0 = format & 0xff; // single PRACH format format1 = (format >> 8) & 0xff; // dual PRACH format - ul_config->sfn = frameP; - ul_config->slot = slotP; - - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); - ul_config->number_pdus += 1; + + fill_ul_config(ul_config, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH); + LOG_D(PHY, "In %s: (%p) %d UL PDUs:\n", __FUNCTION__, ul_config, ul_config->number_pdus); ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); @@ -1767,11 +1765,10 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s AssertFatal(1 == 0, "Invalid PRACH format"); } } // if format1 + fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); } // is_nr_prach_slot - - fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) - mac->if_module->scheduled_response(&scheduled_response); } // if is_nr_UL_slot } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index bce0719556..39bad35af7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -127,8 +127,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; frequency_range_t frequency_range = band<100?FR1:FR2; - lte_frame_type_t frame_type; - get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type); + lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); RC.nrmac[Mod_idP]->common_channels[0].frame_type = frame_type; // Cell configuration @@ -311,8 +310,6 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm } - - extern uint16_t sl_ahead; int rrc_mac_config_req_gNB(module_id_t Mod_idP, int ssb_SubcarrierOffset, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 4ada9eb9f3..de9c64cd46 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -66,11 +66,15 @@ void dump_mac_stats(gNB_MAC_INST *gNB) int num = 1; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d)\n", UE_id, UE_info->rnti[UE_id], num++, UE_info->num_UEs); - const NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; - LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n", + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0; + LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d, average RSRP %d (%d meas)\n", UE_id, stats->dlsch_rounds[0], stats->dlsch_rounds[1], - stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors); + stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors, + avg_rsrp, stats->num_rsrp_meas); + stats->num_rsrp_meas = 0; + stats->cumul_rsrp = 0 ; LOG_I(MAC, "UE %d: dlsch_total_bytes %d\n", UE_id, stats->dlsch_total_bytes); LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n", UE_id, @@ -365,7 +369,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, /* send tick to RLC and RRC every ms */ if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) { void nr_rlc_tick(int frame, int subframe); + void nr_pdcp_tick(int frame, int subframe); nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing); + nr_pdcp_tick(frame, slot >> *scc->ssbSubcarrierSpacing); nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index ac3a4e77d2..64867c5be5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -245,7 +245,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][slotP]; nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; - if (is_nr_UL_slot(scc,slotP)) { + if (is_nr_UL_slot(scc, slotP, cc->frame_type)) { + uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot; uint16_t RA_sfn_index = -1; @@ -647,7 +648,8 @@ void nr_get_Msg3alloc(module_id_t module_id, NR_RA_t *ra) { // msg3 is schedulend in mixed slot in the following TDD period - // for now we consider a TBS of 18 bytes + + uint16_t msg3_nb_rb = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // sdu has 6 or 8 bytes int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing; int StartSymbolIndex, NrOfSymbols, startSymbolAndLength, temp_slot; @@ -677,21 +679,22 @@ void nr_get_Msg3alloc(module_id_t module_id, uint16_t *vrb_map_UL = &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE]; const uint16_t bwpSize = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - /* search 18 free RBs */ + + /* search msg3_nb_rb free RBs */ int rbSize = 0; int rbStart = 0; - while (rbSize < 18) { + while (rbSize < msg3_nb_rb) { rbStart += rbSize; /* last iteration rbSize was not enough, skip it */ rbSize = 0; while (rbStart < bwpSize && vrb_map_UL[rbStart]) rbStart++; - AssertFatal(rbStart < bwpSize - 18, "no space to allocate Msg 3 for RA!\n"); + AssertFatal(rbStart < bwpSize - msg3_nb_rb, "no space to allocate Msg 3 for RA!\n"); while (rbStart + rbSize < bwpSize && !vrb_map_UL[rbStart + rbSize] - && rbSize < 18) + && rbSize < msg3_nb_rb) rbSize++; } - ra->msg3_nb_rb = 18; + ra->msg3_nb_rb = msg3_nb_rb; ra->msg3_first_rb = rbStart; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 1de46aaea4..3f69cfbe74 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -235,6 +235,7 @@ void schedule_control_sib1(module_id_t module_id, int time_domain_allocation, uint8_t mcsTableIdx, uint8_t mcs, + uint8_t candidate_idx, int num_total_bytes) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; @@ -266,13 +267,10 @@ void schedule_control_sib1(module_id_t module_id, gNB_mac->sched_ctrlCommon->coreset, gNB_mac->sched_ctrlCommon->aggregation_level, 0, - 0, + candidate_idx, nr_of_candidates); - if (gNB_mac->sched_ctrlCommon->cce_index < 0) { - LOG_E(MAC, "%s(): could not find CCE for coreset0\n", __func__); - return; - } + AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n"); const uint16_t bwpSize = gNB_mac->type0_PDCCH_CSS_config.num_rbs; int rbStart = gNB_mac->type0_PDCCH_CSS_config.cset_start_rb; @@ -301,9 +299,7 @@ void schedule_control_sib1(module_id_t module_id, TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx), rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3; - - // FIXME: Something is not working in nr_modulation() for TBS = 84, so we need to skip it - } while ( (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes) || (TBS==84) ); + } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes); gNB_mac->sched_ctrlCommon->rbSize = rbSize; gNB_mac->sched_ctrlCommon->rbStart = 0; @@ -467,6 +463,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) int time_domain_allocation = 0; uint8_t mcsTableIdx = 0; uint8_t mcs = 6; + uint8_t candidate_idx = 0; gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; @@ -482,7 +479,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) for (int i=0;iphy_test || get_softmodem_params()->do_ra) { + else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra || get_softmodem_params()->sa) { /* we will need the large header, phy-test typically allocates all * resources and fills to the last byte below */ NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 00e53dd21e..37cafff9cc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -647,6 +647,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, int res_found = 0; pucch_pdu->bit_len_harq = O_ack; + pucch_pdu->bit_len_csi_part1 = O_csi; uint16_t O_uci = O_csi + O_ack; @@ -699,6 +700,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, n_set = pucch_Config->resourceSetToAddModList->list.count; AssertFatal(n_set>0,"PUCCH resourceSetToAddModList is empty\n"); + LOG_D(MAC, "UCI n_set= %d\n", n_set); + N2 = 2; // procedure to select pucch resource id from resource sets according to // number of uci bits and pucch resource indicator pucch_resource @@ -1642,7 +1645,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secon add_nr_list(&UE_info->list, UE_id); memset(&UE_info->mac_stats[UE_id], 0, sizeof(NR_mac_stats_t)); set_Y(UE_info->Y[UE_id], rntiP); - compute_csi_bitlen(secondaryCellGroup, UE_info, UE_id); + compute_csi_bitlen (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup, UE_info, UE_id, mod_idP); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; memset(sched_ctrl, 0, sizeof(*sched_ctrl)); sched_ctrl->ta_frame = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 3ae3707962..a6f7105769 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -80,6 +80,42 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, pucch->sr_flag); } +#define MIN_RSRP_VALUE -141 +#define MAX_NUM_SSB 128 +#define MAX_SSB_SCHED 8 +#define L1_RSRP_HYSTERIS 10 //considering 10 dBm as hysterisis for avoiding frequent SSB Beam Switching. !Fixme provide exact value if any +//#define L1_DIFF_RSRP_STEP_SIZE 2 + +int ssb_index_sorted[MAX_NUM_SSB] = {0}; +int ssb_rsrp_sorted[MAX_NUM_SSB] = {0}; + +//Measured RSRP Values Table 10.1.16.1-1 from 36.133 +//Stored all the upper limits[Max RSRP Value of corresponding index] +//stored -1 for invalid values +int L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, //0 - 9 + -1, -1, -1, -1, -1, -1, -140, -139, -138, -137, //10 - 19 + -136, -135, -134, -133, -132, -131, -130, -129, -128, -127, //20 - 29 + -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, //30 - 39 + -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, //40 - 49 + -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, //50 - 59 + -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, //60 - 69 + -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, //70 - 79 + -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, //80 - 89 + -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, //90 - 99 + -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, //100 - 109 + -46, -45, -44, -44, -1, -1, -1, -1, -1, -1, //110 - 119 + -1, -1, -1, -1, -1, -1, -1, -1//120 - 127 + }; + +//Differential RSRP values Table 10.1.6.1-2 from 36.133 +//Stored the upper limits[MAX RSRP Value] +int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { + 0, -2, -4, -6, -8, -10, -12, -14, -16, -18, //0 - 9 + -20, -22, -24, -26, -28, -30 //10 - 15 +}; + + void nr_schedule_pucch(int Mod_idP, frame_t frameP, sub_frame_t slotP) { @@ -106,74 +142,293 @@ void nr_schedule_pucch(int Mod_idP, } +//! Calculating number of bits set +uint8_t number_of_bits_set (uint8_t buf,uint8_t * max_ri){ + uint8_t nb_of_bits_set = 0; + uint8_t mask = 0xff; + uint8_t index = 0; + + for (index=7; (buf & mask) && (index>=0) ; index--){ + if (buf & (1<>=1; + } + *max_ri = 8-index; + return nb_of_bits_set; +} + + //!TODO : same function can be written to handle csi_resources -void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) { +void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP){ uint8_t csi_report_id = 0; uint8_t csi_resourceidx =0; uint8_t csi_ssb_idx =0; - - NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; NR_CSI_ResourceConfigId_t csi_ResourceConfigId; + for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ - csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement; - UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present; + struct NR_CSI_ReportConfig *csi_reportconfig = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + nr_csi_report_t *csi_report = &UE_info->csi_report_template[UE_id][csi_report_id]; + csi_ResourceConfigId=csi_reportconfig->resourcesForChannelMeasurement; + reportQuantity_type = csi_reportconfig->reportQuantity.present; + csi_report->reportQuantity_type = reportQuantity_type; for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { - if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId) - continue; + struct NR_CSI_ResourceConfig *csi_resourceconfig = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]; + if ( csi_resourceconfig->csi_ResourceConfigId != csi_ResourceConfigId) + continue; else { - //Finding the CSI_RS or SSB Resources - UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present; - if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){ - struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB; + uint8_t nb_ssb_resources =0; + //Finding the CSI_RS or SSB Resources + if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) { - UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0; - UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0; + if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == csi_reportconfig->groupBasedBeamReporting.present) { + if (NULL != csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + csi_report->CSI_report_bitlen.nb_ssbri_cri = *(csi_reportconfig->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; + else + /*! From Spec 38.331 + * nrofReportedRS + * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE + * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. + * When the field is absent the UE applies the value 1 + */ + csi_report->CSI_report_bitlen.nb_ssbri_cri= 1; + }else + csi_report->CSI_report_bitlen.nb_ssbri_cri= 2; + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == csi_report->reportQuantity_type) { + for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) { + if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])){ + + ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig + nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; + csi_report->SSB_Index_list = csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.array; + csi_report->CSI_Index_list = NULL; + break; + } + } + } else /*if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type)*/{ + for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.count; csi_ssb_idx++) { + if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { + + ///For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 + nb_ssb_resources= csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count; + csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.array; + csi_report->SSB_Index_list = NULL; + break; + } + } + } + + if (nb_ssb_resources) { + csi_report->CSI_report_bitlen.cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources)); + csi_report->CSI_report_bitlen.rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + csi_report->CSI_report_bitlen.diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + } else { + csi_report->CSI_report_bitlen.cri_ssbri_bitlen =0; + csi_report->CSI_report_bitlen.rsrp_bitlen = 0; + csi_report->CSI_report_bitlen.diff_rsrp_bitlen =0; + } + + LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d\n", + csi_report->CSI_report_bitlen.cri_ssbri_bitlen, + csi_report->CSI_report_bitlen.rsrp_bitlen, + csi_report->CSI_report_bitlen.diff_rsrp_bitlen); } - if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){ - uint8_t nb_ssb_resources =0; + uint8_t ri_restriction; + uint8_t ri_bitlen; + uint8_t nb_allowed_ri; + uint8_t max_ri; + + if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI==reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI==reportQuantity_type|| + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1==reportQuantity_type){ + for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) { - if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId == - *(csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { - ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig - if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == - csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) { - if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS) - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; - else - /*! From Spec 38.331 - * nrofReportedRS - * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE - * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. - * When the field is absent the UE applies the value 1 - */ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1; - } else - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2; + if (csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_ResourceSetId == + *(csi_resourceconfig->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.array[0])) { + ///For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 for spec 38.212 + nb_ssb_resources= csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.count; + csi_report->CSI_Index_list = csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list.array[csi_ssb_idx]->nzp_CSI_RS_Resources.list.array; + csi_report->SSB_Index_list = NULL; + } + break; + } + csi_report->csi_meas_bitlen.cri_bitlen=ceil(log2 (nb_ssb_resources)); - nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; - if (nb_ssb_resources){ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources)); - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP - } - else{ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0; - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0; - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0; - } + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){ - LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d\n", - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen, - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen, - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen); - break ; + switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value) { + case 1:; + csi_report->csi_meas_bitlen.ri_bitlen=0; + break; + case 2: + /* From Spec 38.212 + * If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator + * values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6, + * TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause + * 5.2.2.2.1 [6, TS 38.214]. + * + * But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to + * calculate RI for antennas equal or more than two. + * */ + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present */ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0), &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction, &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + ri_bitlen = ri_bitlen<1?ri_bitlen:1; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + break; + case 4: + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present */ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0), &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction,&max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + ri_bitlen = ri_bitlen<2?ri_bitlen:2; //from the spec 38.212 and table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + break; + case 6: + case 8: + AssertFatal (NULL!=csi_reportconfig->dummy, "nrofCQIsPerReport is not present"); + + ri_restriction = csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->typeI_SinglePanel_ri_Restriction.buf[0]; + + /* Replace dummy with the nrofCQIsPerReport from the CSIreport + config when equalent ASN structure present */ + if (0==*(csi_reportconfig->dummy)){ + nb_allowed_ri = number_of_bits_set((ri_restriction & 0xf0),&max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + else{ + nb_allowed_ri = number_of_bits_set(ri_restriction, &max_ri); + ri_bitlen = ceil(log2(nb_allowed_ri)); + } + csi_report->csi_meas_bitlen.ri_bitlen=ri_bitlen; + break; + default: + AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value); + } + } + csi_report->csi_meas_bitlen.li_bitlen=0; + csi_report->csi_meas_bitlen.cqi_bitlen=0; + csi_report->csi_meas_bitlen.pmi_x1_bitlen=0; + csi_report->csi_meas_bitlen.pmi_x2_bitlen=0; + } + + if( NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type ){ + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){ + + switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value) { + case 1:; + csi_report->csi_meas_bitlen.li_bitlen=0; + break; + case 2: + case 4: + case 6: + case 8: + /* From Spec 38.212 + * If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator + * values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6, + * TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause + * 5.2.2.2.1 [6, TS 38.214]. + * + * But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to + * calculate RI for antennas equal or more than two. + * */ + //! TODO: The bit length of LI is as follows LI = log2(RI), Need to confirm wheather we should consider maximum RI can be reported from ri_restricted + // or we should consider reported RI. If we need to consider reported RI for calculating LI bit length then we need to modify the code. + csi_report->csi_meas_bitlen.li_bitlen=ceil(log2(max_ri))<2?ceil(log2(max_ri)):2; + break; + default: + AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value); + } + } + } + + if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_CQI==reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_i1_CQI==reportQuantity_type){ + + switch (RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value){ + case 1: + case 2: + case 4: + case 6: + case 8: + /* From Spec 38.212 + * If the higher layer parameter nrofCQIsPerReport=1, nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator + * values in the 4 LSBs of the higher layer parameter typeI-SinglePanel-ri-Restriction according to Subclause 5.2.2.2.1 [6, + * TS 38.214]; otherwise nRI in Table 6.3.1.1.2-3 is the number of allowed rank indicator values according to Subclause + * 5.2.2.2.1 [6, TS 38.214]. + * + * But from Current RRC ASN structures nrofCQIsPerReport is not present. Present a dummy variable is present so using it to + * calculate RI for antennas equal or more than two. + * */ + + if (max_ri > 4 && max_ri < 8){ + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){ + if (NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI==csi_reportconfig->reportFreqConfiguration->cqi_FormatIndicator) + csi_report->csi_meas_bitlen.cqi_bitlen = 8; + else + csi_report->csi_meas_bitlen.cqi_bitlen = 4; + } + }else{ //This condition will work even for type1-multipanel. + if (NR_CSI_ReportConfig__reportFreqConfiguration__cqi_FormatIndicator_widebandCQI==csi_reportconfig->reportFreqConfiguration->cqi_FormatIndicator) + csi_report->csi_meas_bitlen.cqi_bitlen = 4; + else + csi_report->csi_meas_bitlen.cqi_bitlen = 2; + } + break; + default: + AssertFatal(RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value>8,"Number of antennas %d are out of range", RC.nrmac[Mod_idP]->config[0].carrier_config.num_tx_ant.value); + } + } + if (NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI==reportQuantity_type){ + if (NR_CodebookConfig__codebookType__type1__subType_PR_typeI_SinglePanel==csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.present){ + switch (csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present){ + case NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two: + if (max_ri ==1) + csi_report->csi_meas_bitlen.pmi_x1_bitlen = 2; + else if (max_ri ==2) + csi_report->csi_meas_bitlen.pmi_x1_bitlen = 1; + break; + default: + AssertFatal(csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present!= + NR_CodebookConfig__codebookType__type1__subType__typeI_SinglePanel__nrOfAntennaPorts_PR_two, + "Not handled Yet %d", csi_reportconfig->codebookConfig->codebookType.choice.type1->subType.choice.typeI_SinglePanel->nrOfAntennaPorts.present); + break; } } } - if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report) - AssertFatal(1==0,"Currently configuring only SSB beamreporting."); break; } } @@ -181,12 +436,27 @@ void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t } -uint16_t nr_get_csi_bitlen(const nr_csi_report_t *csi_report) -{ - const CRI_SSBRI_RSRP_bitlen_t *bitlen = &csi_report->CSI_report_bitlen[0]; - return bitlen->cri_ssbri_bitlen * bitlen->nb_ssbri_cri - + bitlen->rsrp_bitlen - + bitlen->diff_rsrp_bitlen * (bitlen->nb_ssbri_cri - 1) * csi_report->nb_of_csi_ssb_report; +uint16_t nr_get_csi_bitlen(int Mod_idP, + int UE_id, + uint8_t csi_report_id) { + + uint16_t csi_bitlen =0; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + L1_RSRP_bitlen_t * CSI_report_bitlen = NULL; + CSI_Meas_bitlen_t * csi_meas_bitlen = NULL; + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP==UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type|| + NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP==UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type){ + CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements + csi_bitlen+= ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + + CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * + (CSI_report_bitlen->nb_ssbri_cri -1 ))); + } else{ + csi_meas_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].csi_meas_bitlen); //This might need to be moodif for Aperiodic CSI-RS measurements + csi_bitlen+= (csi_meas_bitlen->cri_bitlen +csi_meas_bitlen->ri_bitlen+csi_meas_bitlen->li_bitlen+csi_meas_bitlen->cqi_bitlen+csi_meas_bitlen->pmi_x1_bitlen+csi_meas_bitlen->pmi_x2_bitlen); + } + + return csi_bitlen; } @@ -246,7 +516,7 @@ void nr_csi_meas_reporting(int Mod_idP, curr_pucch->ul_slot = sched_slot; curr_pucch->resource_indicator = res_index; curr_pucch->csi_bits += - nr_get_csi_bitlen(&UE_info->csi_report_template[UE_id][csi_report_id]); + nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // going through the list of PUCCH resources to find the one indexed by resource_id uint16_t *vrb_map_UL = &RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; @@ -314,6 +584,375 @@ static void handle_dl_harq(module_id_t mod_id, } } +int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, int Mod_idP, int UE_id) { + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id] ; + int nb_tci_states = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.count; + NR_TCI_State_t *tci =NULL; + int i; + + for(i=0; ispCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.array[i]; + + if(tci != NULL) { + if(tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t) + return tci->tci_StateId; // returned TCI state ID + } + // if type2 is configured + else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type2->referenceSignal.choice.ssb == ssb_index_t) + return tci->tci_StateId; // returned TCI state ID + } else LOG_I(MAC,"SSB index is not found in first 64 TCI states of TCI_statestoAddModList[%d]", i); + } + } + + // tci state not identified in first 64 TCI States of PDSCH Config + return -1; +} + +int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, int Mod_idP, int UE_id) { + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id] ; + int nb_tci_states = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.count; + NR_TCI_State_t *tci =NULL; + NR_TCI_StateId_t *tci_id = NULL; + int bwp_id = 1; + NR_BWP_Downlink_t *bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + NR_ControlResourceSet_t *coreset = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]; + int i; + int flag = 0; + int tci_stateID = -1; + + for(i=0; ispCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList->list.array[i]; + + if(tci != NULL && tci->qcl_Type1.referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + if(tci->qcl_Type1.referenceSignal.choice.ssb == ssb_index_t) { + flag = 1; + tci_stateID = tci->tci_StateId; + break; + } else if(tci->qcl_Type2 != NULL && tci->qcl_Type2->referenceSignal.present == NR_QCL_Info__referenceSignal_PR_ssb) { + flag = 1; + tci_stateID = tci->tci_StateId; + break; + } + } + + if(flag != 0 && tci_stateID != -1 && coreset != NULL) { + for(i=0; i<64 && itci_StatesPDCCH_ToAddList->list.count; i++) { + tci_id = coreset->tci_StatesPDCCH_ToAddList->list.array[i]; + + if(tci_id != NULL && *tci_id == tci_stateID) + return tci_stateID; + } + } + } + + // Need to implement once configuration is received + return -1; +} + +//returns the measured RSRP value (upper limit) +int get_measured_rsrp(uint8_t index) { + //if index is invalid returning minimum rsrp -140 + if((index >= 0 && index <= 15) || index >= 114) + return MIN_RSRP_VALUE; + + return L1_SSB_CSI_RSRP_measReport_mapping_38133_10_1_6_1_1[index]; +} + +//returns the differential RSRP value (upper limit) +int get_diff_rsrp(uint8_t index, int strongest_rsrp) { + if(strongest_rsrp != -1) { + return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; + } else + return MIN_RSRP_VALUE; +} + +//identifies the target SSB Beam index +//keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally +//handles triggering of PDCCH and PDSCH MAC CEs +void tci_handling(module_id_t Mod_idP, int UE_id, frame_t frame, slot_t slot) { + + int strongest_ssb_rsrp = 0; + int cqi_idx = 0; + int curr_ssb_beam_index = 0; //ToDo: yet to know how to identify the serving ssb beam index + uint8_t target_ssb_beam_index = curr_ssb_beam_index; + uint8_t is_triggering_ssb_beam_switch =0; + uint8_t ssb_idx = 0; + int pdsch_bwp_id =0; + int ssb_index[MAX_NUM_SSB] = {0}; + int ssb_rsrp[MAX_NUM_SSB] = {0}; + uint8_t idx = 0; + int bwp_id = 1; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; + NR_BWP_Downlink_t *bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + //bwp indicator + int n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; + uint8_t nr_ssbri_cri = 0; + uint8_t nb_of_csi_ssb_report = UE_info->csi_report_template[UE_id][cqi_idx].nb_of_csi_ssb_report; + int better_rsrp_reported = -140-(-0); /*minimum_measured_RSRP_value - minimum_differntail_RSRP_value*///considering the minimum RSRP value as better RSRP initially + uint8_t diff_rsrp_idx = 0; + uint8_t i, j; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + + if (n_dl_bwp < 4) + pdsch_bwp_id = bwp_id; + else + pdsch_bwp_id = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 + + /*Example: + CRI_SSBRI: 1 2 3 4| 5 6 7 8| 9 10 1 2| + nb_of_csi_ssb_report = 3 //3 sets as above + nr_ssbri_cri = 4 //each set has 4 elements + storing ssb indexes in ssb_index array as ssb_index[0] = 1 .. ssb_index[4] = 5 + ssb_rsrp[0] = strongest rsrp in first set, ssb_rsrp[4] = strongest rsrp in second set, .. + idx: resource set index + */ + + //for all reported SSB + for (idx = 0; idx < nb_of_csi_ssb_report; idx++) { + nr_ssbri_cri = sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri; + //extracting the ssb indexes + for (ssb_idx = 0; ssb_idx < nr_ssbri_cri; ssb_idx++) { + ssb_index[idx * nb_of_csi_ssb_report + ssb_idx] = sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI[ssb_idx]; + } + + //if strongest measured RSRP is configured + strongest_ssb_rsrp = get_measured_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP); + // including ssb rsrp in mac stats + stats->cumul_rsrp += strongest_ssb_rsrp; + stats->num_rsrp_meas++; + ssb_rsrp[idx * nb_of_csi_ssb_report] = strongest_ssb_rsrp; + LOG_D(MAC,"ssb_rsrp = %d\n",strongest_ssb_rsrp); + + //if current ssb rsrp is greater than better rsrp + if(ssb_rsrp[idx * nb_of_csi_ssb_report] > better_rsrp_reported) { + better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report]; + target_ssb_beam_index = idx * nb_of_csi_ssb_report; + } + + for(diff_rsrp_idx =1; diff_rsrp_idx < nr_ssbri_cri; diff_rsrp_idx++) { + ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] = get_diff_rsrp(sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx-1], strongest_ssb_rsrp); + + //if current reported rsrp is greater than better rsrp + if(ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx] > better_rsrp_reported) { + better_rsrp_reported = ssb_rsrp[idx * nb_of_csi_ssb_report + diff_rsrp_idx]; + target_ssb_beam_index = idx * nb_of_csi_ssb_report + diff_rsrp_idx; + } + } + } + + + if(ssb_index[target_ssb_beam_index] != ssb_index[curr_ssb_beam_index] && ssb_rsrp[target_ssb_beam_index] > ssb_rsrp[curr_ssb_beam_index]) { + if( ssb_rsrp[target_ssb_beam_index] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + is_triggering_ssb_beam_switch = 1; + LOG_D(MAC, "Triggering ssb beam switching using tci\n"); + } + } + + if(is_triggering_ssb_beam_switch) { + //filling pdcch tci state activativation mac ce structure fields + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 1; + //OAI currently focusing on Non CA usecase hence 0 is considered as serving + //cell id + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.servingCellId = 0; //0 for PCell as 38.331 v15.9.0 page 353 //serving cell id for which this MAC CE applies + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId = 0; //coreset id for which the TCI State id is being indicated + + /* 38.321 v15.8.0 page 66 + TCI State ID: This field indicates the TCI state identified by TCI-StateId as specified in TS 38.331 [5] applicable + to the Control Resource Set identified by CORESET ID field. + If the field of CORESET ID is set to 0, + this field indicates a TCI-StateId for a TCI state of the first 64 TCI-states configured by tci-States-ToAddModList and tciStates-ToReleaseList in the PDSCH-Config in the active BWP. + If the field of CORESET ID is set to the other value than 0, + this field indicates a TCI-StateId configured by tci-StatesPDCCH-ToAddList and tciStatesPDCCH-ToReleaseList in the controlResourceSet identified by the indicated CORESET ID. + The length of the field is 7 bits + */ + if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.coresetId == 0) { + int tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index[target_ssb_beam_index], Mod_idP, UE_id); + + if( tci_state_id != -1) + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + else { + //identify the best beam within first 64 TCI States of PDSCH + //Config TCI-states-to-addModList + int flag = 0; + + for(i =0; ssb_index_sorted[i]!=0; i++) { + tci_state_id = checkTargetSSBInFirst64TCIStates_pdschConfig(ssb_index_sorted[i], Mod_idP, UE_id) ; + + if(tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + flag = 1; + break; + } + } + + if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0; + } + } + } else { + int tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index[target_ssb_beam_index], Mod_idP, UE_id); + + if (tci_state_id !=-1) + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + else { + //identify the best beam within CORESET/PDCCH + ////Config TCI-states-to-addModList + int flag = 0; + + for(i =0; ssb_index_sorted[i]!=0; i++) { + tci_state_id = checkTargetSSBInTCIStates_pdcchConfig(ssb_index_sorted[i], Mod_idP, UE_id); + + if( tci_state_id != -1 && ssb_rsrp_sorted[i] > ssb_rsrp[curr_ssb_beam_index] && ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] > L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tciStateId = tci_state_id; + flag = 1; + break; + } + } + + if(flag == 0 || ssb_rsrp_sorted[i] < ssb_rsrp[curr_ssb_beam_index] || ssb_rsrp_sorted[i] - ssb_rsrp[curr_ssb_beam_index] < L1_RSRP_HYSTERIS) { + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.is_scheduled = 0; + } + } + } + + sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI = bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.array[bwp_id-1]->tci_PresentInDCI; + + //filling pdsch tci state activation deactivation mac ce structure fields + if(sched_ctrl->UE_mac_ce_ctrl.pdcch_state_ind.tci_present_inDCI) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.is_scheduled = 1; + /* + Serving Cell ID: This field indicates the identity of the Serving Cell for which the MAC CE applies + Considering only PCell exists. Serving cell index of PCell is always 0, hence configuring 0 + */ + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.servingCellId = 0; + /* + BWP ID: This field indicates a DL BWP for which the MAC CE applies as the codepoint of the DCI bandwidth + part indicator field as specified in TS 38.212 + */ + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.bwpId = pdsch_bwp_id; + + /* + * TODO ssb_rsrp_sort() API yet to code to find 8 best beams, rrc configuration + * is required + */ + for(i = 0; i<8; i++) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i] = i; + } + + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.highestTciStateActivated = 8; + + for(i = 0, j =0; iUE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.tciStateActDeact[i]) { + sched_ctrl->UE_mac_ce_ctrl.pdsch_TCI_States_ActDeact.codepoint[j] = i; + j++; + } + } + }//tci_presentInDCI + }//is-triggering_beam_switch +}//tci handling + +void reverse_n_bits(uint8_t *value, uint16_t bitlen) { + uint16_t j; + uint8_t i; + for(j = bitlen - 1,i = 0; j > i; j--, i++) { + if(((*value>>j)&1) != ((*value>>i)&1)) { + *value ^= (1<csi_part1.csi_part1_bit_len)/8); + uint8_t *payload = uci_pdu->csi_part1.csi_part1_payload; + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type = NR_CSI_ReportConfig__reportQuantity_PR_NOTHING; + NR_UE_info_t *UE_info = &(RC.nrmac[Mod_idP]->UE_info); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + uint8_t csi_report_id = 0; + + UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = 0; + for ( csi_report_id =0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++ ) { + //Has to implement according to reportSlotConfig type + /*reportQuantity must be considered according to the current scheduled + CSI-ReportConfig if multiple CSI-ReportConfigs present*/ + reportQuantity_type = UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type; + LOG_D(PHY,"SFN/SF:%d%d reportQuantity type = %d\n",frame,slot,reportQuantity_type); + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type || + NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP == reportQuantity_type) { + uint8_t csi_ssb_idx = 0; + uint8_t diff_rsrp_idx = 0; + uint8_t cri_ssbri_bitlen = UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.cri_ssbri_bitlen; + + /*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report + * the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE + * From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set + * From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 + */ + + /** from 38.214 sec 5.2.1.4.2 + - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE is + not required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in + a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting + + - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE is not + required to update measurements for more than 64 CSI-RS and/or SSB resources, and the UE shall report in a + single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB + resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with + multiple simultaneous spatial domain receive filter + */ + + idx = 0; //Since for SSB RSRP reporting in RRC can configure only one ssb resource set per one report config + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri = UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen.nb_ssbri_cri; + + for (csi_ssb_idx = 0; csi_ssb_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri ; csi_ssb_idx++) { + if(cri_ssbri_bitlen > 1) + reverse_n_bits(payload, cri_ssbri_bitlen); + + if (NR_CSI_ReportConfig__reportQuantity_PR_ssb_Index_RSRP == reportQuantity_type) + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = + *(UE_info->csi_report_template[UE_id][csi_report_id].SSB_Index_list[cri_ssbri_bitlen>0?((*payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]); + else + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx] = + *(UE_info->csi_report_template[UE_id][csi_report_id].CSI_Index_list[cri_ssbri_bitlen>0?((*payload)&~(~1<<(cri_ssbri_bitlen-1))):cri_ssbri_bitlen]); + + *payload >>= cri_ssbri_bitlen; + LOG_D(PHY,"SSB_index = %d\n",sched_ctrl->CSI_report[idx].choice.ssb_cri_report.CRI_SSBRI [csi_ssb_idx]); + } + + reverse_n_bits(payload, 7); + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP = (*payload) & 0x7f; + *payload >>= 7; + + for ( diff_rsrp_idx =0; diff_rsrp_idx < sched_ctrl->CSI_report[idx].choice.ssb_cri_report.nr_ssbri_cri - 1; diff_rsrp_idx++ ) { + reverse_n_bits(payload,4); + sched_ctrl->CSI_report[idx].choice.ssb_cri_report.diff_RSRP[diff_rsrp_idx] = (*payload) & 0x0f; + *payload >>= 4; + } + UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report++; + LOG_D(MAC,"csi_payload size = %d, rsrp_id = %d\n",payload_size, sched_ctrl->CSI_report[idx].choice.ssb_cri_report.RSRP); + } + } + + if ( !(reportQuantity_type)) + AssertFatal(reportQuantity_type, "reportQuantity is not configured"); + +} + void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, sub_frame_t slot, @@ -374,17 +1013,19 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) -{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; - UE_info->active[0] = 1; - UE_info->rnti[0] = uci_234->rnti; - int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); +{ int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); return; } - //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_CSI_MeasConfig_t *csi_MeasConfig = RC.nrmac[mod_id]->UE_info.secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - + if (NFAPI_MODE == NFAPI_MODE_PNF){ + UE_info->active[0] = 1; + UE_info->rnti[0] = uci_234->rnti; + } + // tpc (power control) sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_234->ul_cqi, @@ -422,6 +1063,15 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, // handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); // } // } + if ((uci_234->pduBitmap >> 2) & 0x01) { + //API to parse the csi report and store it into sched_ctrl + extract_pucch_csi_report (csi_MeasConfig, uci_234, frame, slot, UE_id, mod_id); + //TCI handling function + tci_handling(mod_id, UE_id,frame, slot); + } + if ((uci_234->pduBitmap >> 3) & 0x01) { + //@TODO:Handle CSI Report 2 + } } @@ -762,5 +1412,4 @@ uint16_t compute_pucch_prb_size(uint8_t format, else{ AssertFatal(1==0,"Not yet implemented"); } - } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 94aa4f5159..23d8f7677f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -396,7 +396,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, T_BUFFER(sduP, sdu_lenP)); UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP; - LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n", + LOG_D(NR_MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d sduP %p\n", gnb_mod_idP, harq_pid, CC_idP, @@ -413,7 +413,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, if (timing_advance != 0xffff) UE_scheduling_control->ta_update = timing_advance; UE_scheduling_control->ul_rssi = rssi; - LOG_D(MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); + LOG_D(NR_MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); } else{ UE_scheduling_control->tpc0 = 1; @@ -432,7 +432,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, #endif if (sduP != NULL){ - LOG_D(MAC, "Received PDU at MAC gNB \n"); + LOG_D(NR_MAC, "Received PDU at MAC gNB \n"); const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size; UE_scheduling_control->sched_ul_bytes -= tb_size; @@ -469,7 +469,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, // random access pusch with TC-RNTI if (ra->rnti != current_rnti) { - LOG_W(MAC, + LOG_W(NR_MAC, "expected TC-RNTI %04x to match current RNTI %04x\n", ra->rnti, current_rnti); @@ -477,19 +477,25 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, } const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->secondaryCellGroup); UE_info->UE_beam_index[UE_id] = ra->beam_id; - LOG_I(MAC, + LOG_I(NR_MAC, "[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, " "adding UE MAC Context UE_id %d/RNTI %04x\n", gnb_mod_idP, current_rnti, UE_id, ra->rnti); + + LOG_D(NR_MAC,"[RAPROC] Received Msg3:\n"); + for (int k = 0; k < sdu_lenP; k++) { + LOG_D(NR_MAC,"(%i): 0x%x\n",k,sduP[k]); + } + // re-initialize ta update variables afrer RA procedure completion UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP; free(ra->preambles.preamble_list); ra->state = RA_IDLE; - LOG_I(MAC, + LOG_I(NR_MAC, "reset RA state information for RA-RNTI %04x/index %d\n", ra->rnti, i); @@ -1069,18 +1075,16 @@ void nr_schedule_ulsch(module_id_t module_id, /* PUSCH PTRS */ if (ps->NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { - // TODO to be fixed from RRC config - uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig - pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); - pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); + bool valid_ptrs_setup = false; pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - - pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + valid_ptrs_setup = set_ul_ptrs_values(ps->NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup, + pusch_pdu->rb_size, pusch_pdu->mcs_index, pusch_pdu->mcs_table, + &pusch_pdu->pusch_ptrs.ptrs_freq_density,&pusch_pdu->pusch_ptrs.ptrs_time_density, + &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset,&pusch_pdu->pusch_ptrs.num_ptrs_ports, + &pusch_pdu->pusch_ptrs.ul_ptrs_power, pusch_pdu->nr_of_symbols); + if (valid_ptrs_setup==true) { + pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + } } else{ pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS @@ -1144,4 +1148,4 @@ void nr_schedule_ulsch(module_id_t module_id, memset(sched_pusch, 0, sizeof(*sched_pusch)); } -} \ No newline at end of file +} diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 3502a11580..c1c7278338 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -73,6 +73,7 @@ void schedule_control_sib1(module_id_t module_id, int time_domain_allocation, uint8_t mcsTableIdx, uint8_t mcs, + uint8_t candidate_idx, int num_total_bytes); void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); @@ -328,7 +329,7 @@ uint16_t compute_pucch_prb_size(uint8_t format, uint8_t n_symb, uint8_t n_re_ctrl); -void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id); +void compute_csi_bitlen(NR_CSI_MeasConfig_t *csi_MeasConfig, NR_UE_info_t *UE_info, int UE_id, module_id_t Mod_idP); int get_dlscs(nfapi_nr_config_request_t *cfg); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 8dc1303801..33e575d2b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -96,7 +96,7 @@ void mac_top_init_gNB(void) // These should be out of here later pdcp_layer_init(); - if(IS_SOFTMODEM_NOS1 && !get_softmodem_params()->do_ra) + if(IS_SOFTMODEM_NOS1 && !(get_softmodem_params()->do_ra || get_softmodem_params()->sa) ) nr_DRB_preconfiguration(0x1234); rrc_init_nr_global_param(); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 63587d58a4..ac583b5270 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -246,8 +246,17 @@ typedef struct pdcchStateInd { uint8_t servingCellId; uint8_t coresetId; uint8_t tciStateId; + bool tci_present_inDCI; } pdcchStateInd_t; +typedef struct pucchSpatialRelation { + bool is_scheduled; + uint8_t servingCellId; + uint8_t bwpId; + uint8_t pucchResourceId; + bool s0tos7_actDeact[8]; +} pucchSpatialRelation_t; + typedef struct SPCSIReportingpucch { bool is_scheduled; uint8_t servingCellId; @@ -271,12 +280,14 @@ typedef struct pdschTciStatesActDeact { uint8_t bwpId; uint8_t highestTciStateActivated; bool tciStateActDeact[MAX_TCI_STATES]; + uint8_t codepoint[8]; } pdschTciStatesActDeact_t; typedef struct UE_info { sp_zp_csirs_t sp_zp_csi_rs; csi_rs_im_t csi_im; pdcchStateInd_t pdcch_state_ind; + pucchSpatialRelation_t pucch_spatial_relation; SPCSIReportingpucch_t SP_CSI_reporting_pucch; aperiodicCSI_triggerStateSelection_t aperi_CSI_trigger; pdschTciStatesActDeact_t pdsch_TCI_States_ActDeact; @@ -352,6 +363,84 @@ typedef struct NR_UE_harq { uint32_t tb_size; } NR_UE_harq_t; +//! fixme : need to enhace for the multiple TB CQI report + + +// +/*! As per spec 38.214 section 5.2.1.4.2 + * - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'disabled', the UE shall report in + a single report nrofReportedRS (higher layer configured) different CRI or SSBRI for each report setting. + * - if the UE is configured with the higher layer parameter groupBasedBeamReporting set to 'enabled', the UE shall report in a + single reporting instance two different CRI or SSBRI for each report setting, where CSI-RS and/or SSB + resources can be received simultaneously by the UE either with a single spatial domain receive filter, or with + multiple simultaneous spatial domain receive filter +*/ +#define MAX_NR_OF_REPORTED_RS 4 + +typedef enum NR_CSI_Report_Config { + CSI_Report_PR_cri_ri_li_pmi_cqi_report, + CSI_Report_PR_ssb_cri_report +} NR_CSI_Report_Config_PR; +struct CRI_RI_LI_PMI_CQI { + uint8_t cri; + uint8_t ri; + uint8_t li; + uint8_t pmi_x1; + uint8_t pmi_x2; + uint8_t cqi; +}; + +typedef struct CRI_SSB_RSRP { + uint8_t nr_ssbri_cri; + uint8_t CRI_SSBRI[MAX_NR_OF_REPORTED_RS]; + uint8_t RSRP; + uint8_t diff_RSRP[MAX_NR_OF_REPORTED_RS - 1]; +} CRI_SSB_RSRP_t; + +struct CSI_Report { + NR_CSI_Report_Config_PR present; + union Config_CSI_Report { + struct CRI_RI_LI_PMI_CQI cri_ri_li_pmi_cqi_report; + struct CRI_SSB_RSRP ssb_cri_report; + } choice; +}; + +#define MAX_SR_BITLEN 8 + +typedef struct { + uint8_t nb_ssbri_cri; + uint8_t cri_ssbri_bitlen; + uint8_t rsrp_bitlen; + uint8_t diff_rsrp_bitlen; +}L1_RSRP_bitlen_t; + +typedef struct{ + uint8_t cri_bitlen; + uint8_t ri_bitlen; + uint8_t li_bitlen; + uint8_t pmi_x1_bitlen; + uint8_t pmi_x2_bitlen; + uint8_t cqi_bitlen; +} CSI_Meas_bitlen_t; + +typedef struct nr_csi_report { + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; + long periodicity; + uint16_t offset; + long ** SSB_Index_list; + long ** CSI_Index_list; +// uint8_t nb_of_nzp_csi_report; + uint8_t nb_of_csi_ssb_report; + L1_RSRP_bitlen_t CSI_report_bitlen; + CSI_Meas_bitlen_t csi_meas_bitlen; +} nr_csi_report_t; + +/*! As per the spec 38.212 and table: 6.3.1.1.2-12 in a single UCI sequence we can have multiple CSI_report + the number of CSI_report will depend on number of CSI resource sets that are configured in CSI-ResourceConfig RRC IE + From spec 38.331 from the IE CSI-ResourceConfig for SSB RSRP reporting we can configure only one resource set + From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1 + */ +#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16 typedef struct NR_UE_old_sched { uint16_t rbSize; int time_domain_allocation; @@ -376,26 +465,8 @@ typedef struct NR_UE_ul_harq { NR_sched_pusch_t sched_pusch; } NR_UE_ul_harq_t; - -typedef struct { - uint8_t nb_ssbri_cri; - uint8_t cri_ssbri_bitlen; - uint8_t rsrp_bitlen; - uint8_t diff_rsrp_bitlen; -}CRI_SSBRI_RSRP_bitlen_t; - - -#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16 -typedef struct nr_csi_report { - NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type; - NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR CSI_Resource_type; - uint8_t nb_of_nzp_csi_report; - uint8_t nb_of_csi_ssb_report; - CRI_SSBRI_RSRP_bitlen_t CSI_report_bitlen[MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG]; -} nr_csi_report_t; - - /*! \brief scheduling control information set through an API */ +#define MAX_CSI_REPORTS 48 typedef struct { /// total amount of data awaiting for this UE uint32_t num_total_bytes; @@ -450,6 +521,8 @@ typedef struct { uint8_t tpc0; uint8_t tpc1; uint16_t ul_rssi; + uint8_t current_harq_pid; + struct CSI_Report CSI_report[MAX_CSI_REPORTS]; /// information about every HARQ process NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; /// HARQ processes that are free @@ -487,6 +560,8 @@ typedef struct { int ulsch_total_bytes_scheduled; int ulsch_total_bytes_rx; int ulsch_current_bytes; + int cumul_rsrp; + uint8_t num_rsrp_meas; } NR_mac_stats_t; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index ffc669a461..eda6888ecd 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -21,24 +21,222 @@ #include "nr_pdcp_entity.h" -#include "nr_pdcp_entity_drb_am.h" +#include +#include +#include + #include "nr_pdcp_security_nea2.h" +#include "nr_pdcp_sdu.h" #include "LOG/log.h" -nr_pdcp_entity_t *new_nr_pdcp_entity_srb( - int is_gnb, int rb_id, - void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size), - void *deliver_sdu_data, - void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size, int sdu_id), - void *deliver_pdu_data) +static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, + char *_buffer, int size) { - abort(); + unsigned char *buffer = (unsigned char *)_buffer; + nr_pdcp_sdu_t *sdu; + int rcvd_sn; + uint32_t rcvd_hfn; + uint32_t rcvd_count; + int header_size; + int integrity_size; + int rx_deliv_sn; + uint32_t rx_deliv_hfn; + + if (size < 1) { + LOG_E(PDCP, "bad PDU received (size = %d)\n", size); + return; + } + + if (!(buffer[0] & 0x80)) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (entity->sn_size == 12) { + rcvd_sn = (((unsigned char)buffer[0] & 0xf) << 8) | + (unsigned char)buffer[1]; + header_size = 2; + } else { + rcvd_sn = (((unsigned char)buffer[0] & 0x3) << 16) | + ((unsigned char)buffer[1] << 8) | + (unsigned char)buffer[2]; + header_size = 3; + } + + integrity_size = 0; + + if (size < header_size + integrity_size + 1) { + LOG_E(PDCP, "bad PDU received (size = %d)\n", size); + return; + } + + rx_deliv_sn = entity->rx_deliv & entity->sn_max; + rx_deliv_hfn = (entity->rx_deliv >> entity->sn_size) & ~entity->sn_max; + + if (rcvd_sn < rx_deliv_sn - entity->window_size) { + rcvd_hfn = rx_deliv_hfn + 1; + } else if (rcvd_sn >= rx_deliv_sn + entity->window_size) { + rcvd_hfn = rx_deliv_hfn - 1; + } else { + rcvd_hfn = rx_deliv_hfn; + } + + rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn; + + if (entity->has_ciphering) + entity->cipher(entity->security_context, + (unsigned char *)buffer+header_size, size-header_size, + entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); + + if (rcvd_count < entity->rx_deliv + || nr_pdcp_sdu_in_list(entity->rx_list, rcvd_count)) { + LOG_D(PDCP, "discard NR PDU rcvd_count=%d\n", rcvd_count); + return; + } + + sdu = nr_pdcp_new_sdu(rcvd_count, + (char *)buffer + header_size, + size - header_size - integrity_size); + entity->rx_list = nr_pdcp_sdu_list_add(entity->rx_list, sdu); + entity->rx_size += size-header_size; + + if (rcvd_count >= entity->rx_next) { + entity->rx_next = rcvd_count + 1; + } + + /* TODO(?): out of order delivery */ + + if (rcvd_count == entity->rx_deliv) { + /* deliver all SDUs starting from rx_deliv up to discontinuity or end of list */ + uint32_t count = entity->rx_deliv; + while (entity->rx_list != NULL && count == entity->rx_list->count) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + count++; + } + entity->rx_deliv = count; + } + + if (entity->t_reordering_start != 0 && entity->rx_deliv > entity->rx_reord) { + /* stop and reset t-Reordering */ + entity->t_reordering_start = 0; + } + + if (entity->t_reordering_start == 0 && entity->rx_deliv < entity->rx_next) { + entity->rx_reord = entity->rx_next; + entity->t_reordering_start = entity->t_current; + } } -nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( +static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity, + char *buffer, int size, int sdu_id) +{ + uint32_t count; + int sn; + int header_size; + char buf[size+3+4]; + + count = entity->tx_next; + sn = entity->tx_next & entity->sn_max; + + if (entity->sn_size == 12) { + buf[0] = 0x80 | ((sn >> 8) & 0xf); + buf[1] = sn & 0xff; + header_size = 2; + } else { + buf[0] = 0x80 | ((sn >> 16) & 0x3); + buf[1] = (sn >> 8) & 0xff; + buf[2] = sn & 0xff; + header_size = 3; + } + + memcpy(buf+header_size, buffer, size); + + if (entity->has_ciphering) + entity->cipher(entity->security_context, + (unsigned char *)buf+header_size, size, + entity->rb_id, count, entity->is_gnb ? 1 : 0); + + entity->tx_next++; + + entity->deliver_pdu(entity->deliver_pdu_data, entity, buf, + size+header_size, sdu_id); +} + +static void nr_pdcp_entity_set_integrity_key(nr_pdcp_entity_t *entity, + char *key) +{ + memcpy(entity->integrity_key, key, 16); +} + +static void check_t_reordering(nr_pdcp_entity_t *entity) +{ + uint32_t count; + + if (entity->t_reordering_start == 0 + || entity->t_current <= entity->t_reordering_start + entity->t_reordering) + return; + + /* stop timer */ + entity->t_reordering_start = 0; + + /* deliver all SDUs with count < rx_reord */ + while (entity->rx_list != NULL && entity->rx_list->count < entity->rx_reord) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + } + + /* deliver all SDUs starting from rx_reord up to discontinuity or end of list */ + count = entity->rx_reord; + while (entity->rx_list != NULL && count == entity->rx_list->count) { + nr_pdcp_sdu_t *cur = entity->rx_list; + entity->deliver_sdu(entity->deliver_sdu_data, entity, + cur->buffer, cur->size); + entity->rx_list = cur->next; + entity->rx_size -= cur->size; + nr_pdcp_free_sdu(cur); + count++; + } + + entity->rx_deliv = count; + + if (entity->rx_deliv < entity->rx_next) { + entity->rx_reord = entity->rx_next; + entity->t_reordering_start = entity->t_current; + } +} + +void nr_pdcp_entity_set_time(struct nr_pdcp_entity_t *entity, uint64_t now) +{ + entity->t_current = now; + + check_t_reordering(entity); +} + +void nr_pdcp_entity_delete(nr_pdcp_entity_t *entity) +{ + nr_pdcp_sdu_t *cur = entity->rx_list; + while (cur != NULL) { + nr_pdcp_sdu_t *next = cur->next; + nr_pdcp_free_sdu(cur); + cur = next; + } + if (entity->free_security != NULL) + entity->free_security(entity->security_context); + free(entity); +} + +nr_pdcp_entity_t *new_nr_pdcp_entity( + nr_pdcp_entity_type_t type, int is_gnb, int rb_id, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), @@ -54,52 +252,56 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( unsigned char *ciphering_key, unsigned char *integrity_key) { - nr_pdcp_entity_drb_am_t *ret; + nr_pdcp_entity_t *ret; - ret = calloc(1, sizeof(nr_pdcp_entity_drb_am_t)); + ret = calloc(1, sizeof(nr_pdcp_entity_t)); if (ret == NULL) { LOG_E(PDCP, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } - ret->common.recv_pdu = nr_pdcp_entity_drb_am_recv_pdu; - ret->common.recv_sdu = nr_pdcp_entity_drb_am_recv_sdu; - ret->common.set_integrity_key = nr_pdcp_entity_drb_am_set_integrity_key; + ret->type = type; - ret->common.delete = nr_pdcp_entity_drb_am_delete; + ret->recv_pdu = nr_pdcp_entity_recv_pdu; + ret->recv_sdu = nr_pdcp_entity_recv_sdu; + ret->set_integrity_key = nr_pdcp_entity_set_integrity_key; + ret->set_time = nr_pdcp_entity_set_time; - ret->common.deliver_sdu = deliver_sdu; - ret->common.deliver_sdu_data = deliver_sdu_data; + ret->delete = nr_pdcp_entity_delete; - ret->common.deliver_pdu = deliver_pdu; - ret->common.deliver_pdu_data = deliver_pdu_data; + ret->deliver_sdu = deliver_sdu; + ret->deliver_sdu_data = deliver_sdu_data; + + ret->deliver_pdu = deliver_pdu; + ret->deliver_pdu_data = deliver_pdu_data; ret->rb_id = rb_id; ret->sn_size = sn_size; ret->t_reordering = t_reordering; ret->discard_timer = discard_timer; - ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1; + ret->sn_max = (1 << sn_size) - 1; + ret->window_size = 1 << (sn_size - 1); if (ciphering_key != NULL && ciphering_algorithm != 0) { if (ciphering_algorithm != 2) { LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n"); exit(1); } - ret->common.has_ciphering = 1; - ret->common.ciphering_algorithm = ciphering_algorithm; - memcpy(ret->common.ciphering_key, ciphering_key, 16); + ret->has_ciphering = 1; + ret->ciphering_algorithm = ciphering_algorithm; + memcpy(ret->ciphering_key, ciphering_key, 16); - ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key); - ret->common.cipher = nr_pdcp_security_nea2_cipher; - ret->common.free_security = nr_pdcp_security_nea2_free_security; + ret->security_context = nr_pdcp_security_nea2_init(ciphering_key); + ret->cipher = nr_pdcp_security_nea2_cipher; + ret->free_security = nr_pdcp_security_nea2_free_security; } - ret->common.is_gnb = is_gnb; + ret->is_gnb = is_gnb; if (integrity_key != NULL) { printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } - return (nr_pdcp_entity_t *)ret; + return ret; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 58d79835ec..36e7a540c4 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -19,18 +19,29 @@ * contact@openairinterface.org */ -#include - #ifndef _NR_PDCP_ENTITY_H_ #define _NR_PDCP_ENTITY_H_ +#include + +#include "nr_pdcp_sdu.h" + +typedef enum { + NR_PDCP_DRB_AM, + NR_PDCP_DRB_UM, + NR_PDCP_SRB +} nr_pdcp_entity_type_t; + typedef struct nr_pdcp_entity_t { + nr_pdcp_entity_type_t type; + /* functions provided by the PDCP module */ void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size); void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size, int sdu_id); void (*delete)(struct nr_pdcp_entity_t *entity); void (*set_integrity_key)(struct nr_pdcp_entity_t *entity, char *key); + void (*set_time)(struct nr_pdcp_entity_t *entity, uint64_t now); /* callbacks provided to the PDCP module */ void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, @@ -39,9 +50,28 @@ typedef struct nr_pdcp_entity_t { void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size, int sdu_id); void *deliver_pdu_data; - int tx_hfn; - int next_nr_pdcp_tx_sn; - int maximum_nr_pdcp_sn; + + /* configuration variables */ + int rb_id; + + int sn_size; /* SN size, in bits */ + int t_reordering; /* unit: ms */ + int discard_timer; /* unit: ms */ + + int sn_max; /* (2^SN_size) - 1 */ + int window_size; /* 2^(SN_size - 1) */ + + /* state variables */ + uint32_t tx_next; + uint32_t rx_next; + uint32_t rx_deliv; + uint32_t rx_reord; + + /* set to the latest know time by the user of the module. Unit: ms */ + uint64_t t_current; + + /* timers (stores the ms of activation, 0 means not active) */ + int t_reordering_start; /* security */ int has_ciphering; @@ -60,18 +90,15 @@ typedef struct nr_pdcp_entity_t { * pdcp entity is for a gnb or an ue */ int is_gnb; + + /* rx management */ + nr_pdcp_sdu_t *rx_list; + int rx_size; + int rx_maxsize; } nr_pdcp_entity_t; -nr_pdcp_entity_t *new_nr_pdcp_entity_srb( - int is_gnb, int rb_id, - void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size), - void *deliver_sdu_data, - void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size, int sdu_id), - void *deliver_pdu_data); - -nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( +nr_pdcp_entity_t *new_nr_pdcp_entity( + nr_pdcp_entity_type_t type, int is_gnb, int rb_id, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c deleted file mode 100644 index 62881c184e..0000000000 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 "nr_pdcp_entity_drb_am.h" - -#include -#include -#include -#include "common/utils/LOG/log.h" - -void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size) -{ - nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; - int sn; - - if (size < 3) abort(); - - if (!(buffer[0] & 0x80)) - LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); - - sn = (((unsigned char)buffer[0] & 0x3) << 16) | - ((unsigned char)buffer[1] << 8) | - (unsigned char)buffer[2]; - - if (entity->common.has_ciphering) - entity->common.cipher(entity->common.security_context, (unsigned char *)buffer+3, size-3, - entity->rb_id, sn, entity->common.is_gnb ? 0 : 1); - - entity->common.deliver_sdu(entity->common.deliver_sdu_data, - (nr_pdcp_entity_t *)entity, buffer+3, size-3); -} - -void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int size, - int sdu_id) -{ - nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; - int sn; - char buf[size+3]; - - sn = entity->common.next_nr_pdcp_tx_sn; - - entity->common.next_nr_pdcp_tx_sn++; - if (entity->common.next_nr_pdcp_tx_sn > entity->common.maximum_nr_pdcp_sn) { - entity->common.next_nr_pdcp_tx_sn = 0; - entity->common.tx_hfn++; - } - - buf[0] = 0x80 | ((sn >> 16) & 0x3); - buf[1] = (sn >> 8) & 0xff; - buf[2] = sn & 0xff; - memcpy(buf+3, buffer, size); - - if (entity->common.has_ciphering) - entity->common.cipher(entity->common.security_context, (unsigned char *)buf+3, size, - entity->rb_id, sn, entity->common.is_gnb ? 1 : 0); - - entity->common.deliver_pdu(entity->common.deliver_pdu_data, - (nr_pdcp_entity_t *)entity, buf, size+3, sdu_id); -} - -void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *key) -{ - /* nothing to do */ -} - -void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity) -{ - nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; - if (entity->common.free_security != NULL) - entity->common.free_security(entity->common.security_context); - free(entity); -} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index f14d25b145..ec48b0adae 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -24,6 +24,7 @@ #endif #include "asn1_utils.h" #include "nr_pdcp_ue_manager.h" +#include "nr_pdcp_timer_thread.h" #include "NR_RadioBearerConfig.h" #include "NR_RLC-BearerConfig.h" #include "NR_RLC-Config.h" @@ -41,6 +42,11 @@ static nr_pdcp_ue_manager_t *nr_pdcp_ue_manager; +/* TODO: handle time a bit more properly */ +static uint64_t nr_pdcp_current_time; +static int nr_pdcp_current_time_last_frame; +static int nr_pdcp_current_time_last_subframe; + /* necessary globals for OAI, not used internally */ hash_table_t *pdcp_coll_p; static uint64_t pdcp_optmask; @@ -339,6 +345,8 @@ void pdcp_layer_init(void) nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1); init_nr_rlc_data_req_queue(); + + nr_pdcp_init_timer_thread(nr_pdcp_ue_manager); } #include "nfapi/oai_integration/vendor_ext.h" @@ -625,11 +633,11 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id, - deliver_sdu_drb, ue, deliver_pdu_drb, ue, - sn_size_dl, t_reordering, discard_timer, - ciphering_algorithm, integrity_algorithm, - ciphering_key, integrity_key); + pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, is_gnb, drb_id, + deliver_sdu_drb, ue, deliver_pdu_drb, ue, + sn_size_dl, t_reordering, discard_timer, + ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); @@ -768,7 +776,7 @@ void nr_DRB_preconfiguration(uint16_t crnti) drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); - *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30; + *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len12bits; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); @@ -976,3 +984,14 @@ void pdcp_mbms_run ( const protocol_ctxt_t *const ctxt_pP){ /* nothing to do */ } + +void nr_pdcp_tick(int frame, int subframe) +{ + if (frame != nr_pdcp_current_time_last_frame || + subframe != nr_pdcp_current_time_last_subframe) { + nr_pdcp_current_time_last_frame = frame; + nr_pdcp_current_time_last_subframe = subframe; + nr_pdcp_current_time++; + nr_pdcp_wakeup_timer_thread(nr_pdcp_current_time); + } +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c new file mode 100644 index 0000000000..47d95156e3 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c @@ -0,0 +1,78 @@ +/* + * 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 "nr_pdcp_sdu.h" + +#include +#include + +nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size) +{ + nr_pdcp_sdu_t *ret = calloc(1, sizeof(nr_pdcp_sdu_t)); + if (ret == NULL) + exit(1); + ret->count = count; + ret->buffer = malloc(size); + if (ret->buffer == NULL) + exit(1); + memcpy(ret->buffer, buffer, size); + ret->size = size; + return ret; +} + +nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu) +{ + nr_pdcp_sdu_t head; + nr_pdcp_sdu_t *cur; + nr_pdcp_sdu_t *prev; + + head.next = l; + cur = l; + prev = &head; + + /* order is by 'count' */ + while (cur != NULL) { + /* check if 'sdu' is before 'cur' in the list */ + if (sdu->count < cur->count) + break; + prev = cur; + cur = cur->next; + } + prev->next = sdu; + sdu->next = cur; + return head.next; +} + +int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count) +{ + while (l != NULL) { + if (l->count == count) + return 1; + l = l->next; + } + return 0; +} + +void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu) +{ + free(sdu->buffer); + free(sdu); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h similarity index 58% rename from openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h rename to openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h index d7c42e6a62..3d4e50a4ce 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h @@ -19,23 +19,21 @@ * contact@openairinterface.org */ -#ifndef _NR_PDCP_ENTITY_DRB_AM_H_ -#define _NR_PDCP_ENTITY_DRB_AM_H_ +#ifndef _NR_PDCP_SDU_H_ +#define _NR_PDCP_SDU_H_ -#include "nr_pdcp_entity.h" +#include -typedef struct { - nr_pdcp_entity_t common; - int rb_id; - int sn_size; /* unit: bits */ - int t_reordering; /* unit: ms */ - int discard_timer; /* unit: ms, -1 means infinity */ -} nr_pdcp_entity_drb_am_t; +typedef struct nr_pdcp_sdu_t { + uint32_t count; + char *buffer; + int size; + struct nr_pdcp_sdu_t *next; +} nr_pdcp_sdu_t; -void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size); -void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *entity, char *buffer, int size, - int sdu_id); -void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *entity, char *key); -void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *entity); +nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size); +nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu); +int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count); +void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu); -#endif /* _NR_PDCP_ENTITY_DRB_AM_H_ */ +#endif /* _NR_PDCP_SDU_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c new file mode 100644 index 0000000000..36e9b16024 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c @@ -0,0 +1,87 @@ +/* + * 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 "nr_pdcp_timer_thread.h" + +#include +#include +#include + +#include "LOG/log.h" + +static pthread_mutex_t timer_thread_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t timer_thread_cond = PTHREAD_COND_INITIALIZER; +static volatile uint64_t timer_thread_curtime = 0; + +static void *nr_pdcp_timer_thread(void *_nr_pdcp_ue_manager) +{ + nr_pdcp_ue_manager_t *nr_pdcp_ue_manager = (nr_pdcp_ue_manager_t *)_nr_pdcp_ue_manager; + nr_pdcp_ue_t **ue_list; + int ue_count; + int i; + int j; + uint64_t curtime = 0; + + while (1) { + if (pthread_mutex_lock(&timer_thread_mutex) != 0) abort(); + while (curtime == timer_thread_curtime) + if (pthread_cond_wait(&timer_thread_cond, &timer_thread_mutex) != 0) abort(); + curtime = timer_thread_curtime; + if (pthread_mutex_unlock(&timer_thread_mutex) != 0) abort(); + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue_list = nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager); + ue_count = nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager); + for (i = 0; i < ue_count; i++) { + for (j = 0; j < 2; j++) { + if (ue_list[i]->srb[j] != NULL) + ue_list[i]->srb[j]->set_time(ue_list[i]->srb[j], curtime); + } + for (j = 0; j < 5; j++) { + if (ue_list[i]->drb[j] != NULL) + ue_list[i]->drb[j]->set_time(ue_list[i]->drb[j], curtime); + } + } + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + } + + return NULL; +} + +void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager) +{ + pthread_t t; + + if (pthread_create(&t, NULL, nr_pdcp_timer_thread, nr_pdcp_ue_manager) != 0) { + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +void nr_pdcp_wakeup_timer_thread(uint64_t time) +{ + if (pthread_mutex_lock(&timer_thread_mutex)) abort(); + timer_thread_curtime = time; + if (pthread_cond_broadcast(&timer_thread_cond)) abort(); + if (pthread_mutex_unlock(&timer_thread_mutex)) abort(); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h new file mode 100644 index 0000000000..db8282f940 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h @@ -0,0 +1,32 @@ +/* + * 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 + */ + +#ifndef _NR_PDCP_TIMER_THREAD_H_ +#define _NR_PDCP_TIMER_THREAD_H_ + +#include "nr_pdcp_ue_manager.h" + +#include + +void nr_pdcp_init_timer_thread(nr_pdcp_ue_manager_t *nr_pdcp_ue_manager); +void nr_pdcp_wakeup_timer_thread(uint64_t time); + +#endif /* _NR_PDCP_TIMER_THREAD_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c index ca51da3d5f..f89a18f94e 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c @@ -189,6 +189,20 @@ void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity ue->drb[drb_id] = entity; } +/* must be called with lock acquired */ +nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->ue_list; +} + +/* must be called with lock acquired */ +int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m) +{ + nr_pdcp_ue_manager_internal_t *m = _m; + return m->ue_count; +} + int nr_pdcp_get_first_rnti(nr_pdcp_ue_manager_t *_m) { nr_pdcp_ue_manager_internal_t *m = _m; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h index 0de2f024b3..3329f856b7 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h @@ -46,6 +46,9 @@ void nr_pdcp_manager_unlock(nr_pdcp_ue_manager_t *m); nr_pdcp_ue_t *nr_pdcp_manager_get_ue(nr_pdcp_ue_manager_t *m, int rnti); void nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager_t *m, int rnti); +nr_pdcp_ue_t **nr_pdcp_manager_get_ue_list(nr_pdcp_ue_manager_t *_m); +int nr_pdcp_manager_get_ue_count(nr_pdcp_ue_manager_t *_m); + /***********************************************************************/ /* ue functions */ /***********************************************************************/ diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 2e0abda556..5a090d4ffd 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -43,7 +43,6 @@ NR_IF_Module_t *if_inst[MAX_IF_MODULES]; NR_Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; - extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); @@ -54,14 +53,7 @@ extern uint16_t sf_ahead; extern uint16_t sl_ahead; void handle_nr_rach(NR_UL_IND_t *UL_info) { - if(NFAPI_MODE == NFAPI_MODE_PNF) { - if (UL_info->rach_ind.number_of_pdus>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); - oai_nfapi_nr_rach_indication(&UL_info->rach_ind); - UL_info->rach_ind.number_of_pdus = 0; - } - } - else { + if (UL_info->rach_ind.number_of_pdus>0) { LOG_I(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); int npdus = UL_info->rach_ind.number_of_pdus; @@ -82,19 +74,10 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } } } -} void handle_nr_uci(NR_UL_IND_t *UL_info) -{ - if(NFAPI_MODE == NFAPI_MODE_PNF) { - if (UL_info->uci_ind.num_ucis>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); - //oai_nfapi_nr_uci_indication(&UL_info->uci_ind); - UL_info->uci_ind.num_ucis = 0; - } - } - else { +{ const module_id_t mod_id = UL_info->module_id; const frame_t frame = UL_info->frame; const sub_frame_t slot = UL_info->slot; @@ -112,6 +95,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); break; } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); @@ -126,24 +110,10 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; } -} + void handle_nr_ulsch(NR_UL_IND_t *UL_info) -{ - if(NFAPI_MODE == NFAPI_MODE_PNF) { - if (UL_info->crc_ind.number_crcs>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); - oai_nfapi_nr_crc_indication(&UL_info->crc_ind); - UL_info->crc_ind.number_crcs = 0; - } - - if (UL_info->rx_ind.number_of_pdus>0) { - //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); - oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); - UL_info->rx_ind.number_of_pdus = 0; - } - } - else { +{ if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { @@ -169,16 +139,17 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot, - rx->rnti, - crc->tb_crc_status ? NULL : rx->pdu, - rx->pdu_length, - rx->timing_advance, - rx->ul_cqi, - rx->rssi); + //Gokul + // nr_rx_sdu(UL_info->module_id, + // UL_info->CC_id, + // UL_info->rx_ind.sfn, + // UL_info->rx_ind.slot, + // rx->rnti, + // crc->tb_crc_status ? NULL : rx->pdu, + // rx->pdu_length, + // rx->timing_advance, + // rx->ul_cqi, + // rx->rssi); //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) @@ -198,11 +169,11 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) UL_info->crc_ind.number_crcs, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); - } } } void NR_UL_indication(NR_UL_IND_t *UL_info) { + //printf("Inside NR UL Indication. \n"); AssertFatal(UL_info!=NULL,"UL_INFO is null\n"); #ifdef DUMP_FAPI dump_ul(UL_info); @@ -274,10 +245,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ifi->NR_Schedule_response(sched_info); } - LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n", - sched_info->frame, - sched_info->slot, - sched_info->DL_req->dl_tti_request_body.nPDUs); + } } } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index edaef6d1ce..51d279b7d1 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -62,7 +62,7 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, unsigned int gNB_index, ui // L2 Abstraction Layer int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint32_t sibs_mask, uint8_t *pduP, uint32_t pdu_len){ - return nr_ue_decode_sib1(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len); + return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, sibs_mask, pduP, pdu_len); } // L2 Abstraction Layer @@ -90,7 +90,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ ret = nr_ue_scheduler(NULL, ul_info); - if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && get_softmodem_params()->do_ra) + if (is_nr_UL_slot(mac->scc, ul_info->slot_tx, mac->frame_type) && get_softmodem_params()->do_ra) nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->thread_id); switch(ret){ diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index d34b4164a2..0e6d5b580f 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -782,21 +782,37 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei; if (r_mme->plmn_Identity != NULL) { - if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) { - /* Use first indicated PLMN MCC if it is defined */ - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[selected_plmn_identity]; + if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count == 3)) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = (*r_mme->plmn_Identity->mcc->list.array[0] & 0xf) * 100 + + (*r_mme->plmn_Identity->mcc->list.array[1] & 0xf) * 10 + + (*r_mme->plmn_Identity->mcc->list.array[2] & 0xf); LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n", ctxt_pP->module_id, S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc, ue_context_pP->ue_context.rnti); } - - if (r_mme->plmn_Identity->mnc.list.count > 0) { - /* Use first indicated PLMN MNC if it is defined */ - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[selected_plmn_identity]; - LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n", + if(r_mme->plmn_Identity->mnc.list.count == 3) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 100 + + (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf) * 10 + + (*r_mme->plmn_Identity->mnc.list.array[2] & 0xf); + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 3; + LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n", ctxt_pP->module_id, S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len, + ue_context_pP->ue_context.rnti); + } + else if(r_mme->plmn_Identity->mnc.list.count == 2) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 10 + + (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf); + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 2; + LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n", + ctxt_pP->module_id, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len, ue_context_pP->ue_context.rnti); } } else { // end if plmn_Identity != NULL diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 6d876a0eef..5aafbaee4c 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -79,17 +79,19 @@ void fill_default_coresetZero(NR_ControlResourceSet_t *coreset0, NR_ServingCellC void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0); void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, - NR_CellGroupConfig_t *secondaryCellGroup, - int scg_id, - int servCellIndex, - int n_physical_antenna_ports, - int initial_csi_index); + NR_ServingCellConfig_t *servingcellconfigdedicated, + NR_CellGroupConfig_t *secondaryCellGroup, + int scg_id, + int servCellIndex, + int n_physical_antenna_ports, + int initial_csi_index); void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, - NR_RRCReconfiguration_IEs_t *reconfig, - NR_CellGroupConfig_t *secondaryCellGroup, - int n_physical_antenna_ports, - int initial_csi_index); + NR_ServingCellConfig_t *servingcellconfigdedicated, + NR_RRCReconfiguration_IEs_t *reconfig, + NR_CellGroupConfig_t *secondaryCellGroup, + int n_physical_antenna_ports, + int initial_csi_index); void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig, int eps_bearer_id, int rb_id, diff --git a/openair2/RRC/NR/nr_rrc_types.h b/openair2/RRC/NR/nr_rrc_types.h index 02495591a9..61f90e3572 100644 --- a/openair2/RRC/NR/nr_rrc_types.h +++ b/openair2/RRC/NR/nr_rrc_types.h @@ -32,11 +32,11 @@ #define RRC_TYPES_NR_H_ typedef enum Rrc_State_NR_e { - RRC_STATE_INACTIVE_NR=0, - RRC_STATE_IDLE_NR, + RRC_STATE_IDLE_NR=0, + RRC_STATE_INACTIVE_NR, RRC_STATE_CONNECTED_NR, - RRC_STATE_FIRST_NR = RRC_STATE_INACTIVE_NR, + RRC_STATE_FIRST_NR = RRC_STATE_IDLE_NR, RRC_STATE_LAST_NR = RRC_STATE_CONNECTED_NR, } Rrc_State_NR_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 6d430d7223..802337257b 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -277,6 +277,8 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration parse_CG_ConfigInfo(rrc,CG_ConfigInfo,NULL); } else { struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_allocate_new_UE_context(rrc); + ue_context_p->ue_context.spCellConfig = calloc(1, sizeof(struct NR_SpCellConfig)); + ue_context_p->ue_context.spCellConfig->spCellConfigDedicated = configuration->scd; LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p); rrc_add_nsa_user(rrc,ue_context_p,NULL); } @@ -631,7 +633,7 @@ rrc_gNB_generate_defaultRRCReconfiguration( DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config)); DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb)); DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer)); - *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_ms30; + *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL)); *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL)); diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 5ea02c7832..e9741aaf78 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -238,11 +238,21 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ cipher_algo, NR_SecurityConfig__keyToUse_secondary); } - fill_default_reconfig(carrier->servingcellconfigcommon, + if (ue_context_p->ue_context.spCellConfig) { + fill_default_reconfig(carrier->servingcellconfigcommon, + ue_context_p->ue_context.spCellConfig->spCellConfigDedicated, reconfig_ies, ue_context_p->ue_context.secondaryCellGroup, carrier->pdsch_AntennaPorts, carrier->initial_csi_index[rrc->Nb_ue]); + } else { + fill_default_reconfig(carrier->servingcellconfigcommon, + NULL, + reconfig_ies, + ue_context_p->ue_context.secondaryCellGroup, + carrier->pdsch_AntennaPorts, + carrier->initial_csi_index[rrc->Nb_ue]); + } ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity; NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config)); memset((void *)CG_Config,0,sizeof(*CG_Config)); @@ -327,7 +337,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ 1024); X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3; itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding - } else if (get_softmodem_params()->do_ra) { + } else if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) { PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, ue_context_p->ue_id_rnti, 0, 0,rrc->module_id); } diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index ab3f192276..8f3993229e 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -31,6 +31,7 @@ #define RRC_GNB_NSA_C #include "NR_ServingCellConfigCommon.h" +#include "NR_ServingCellConfig.h" #include "NR_RRCReconfiguration.h" #include "NR_RRCReconfiguration-IEs.h" #include "NR_CellGroupConfig.h" @@ -135,7 +136,7 @@ void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) { // FIXME: update values from TS38.213 Section 10.1 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE aggregation level for CSS sets configured by searchSpaceSIB1 ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; ss0->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; @@ -143,6 +144,7 @@ void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) { } void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellconfigcommon, + NR_ServingCellConfig_t *servingcellconfigdedicated, NR_CellGroupConfig_t *secondaryCellGroup, int scg_id, int servCellIndex, @@ -172,7 +174,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->cellGroupId = scg_id; NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig)); nr_rlc_bearer_init(RLC_BearerConfig); - if (get_softmodem_params()->do_ra) + if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional); else nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am); @@ -285,7 +287,11 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1 = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1)); secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1->t311 = NR_RLF_TimersAndConstants__ext1__t311_ms30000; secondaryCellGroup->spCellConfig->rlmInSyncOutOfSyncThreshold = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated)); + if (servingcellconfigdedicated) { + secondaryCellGroup->spCellConfig->spCellConfigDedicated = servingcellconfigdedicated; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated)); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->tdd_UL_DL_ConfigurationDedicated = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP)); secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdcch_Config=NULL; @@ -460,9 +466,15 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco #endif secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToReleaseList= NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); + + NR_BWP_Downlink_t *bwp = NULL; + if (servingcellconfigdedicated) { + bwp=servingcellconfigdedicated->downlinkBWP_ToAddModList->list.array[0]; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList)); - NR_BWP_Downlink_t *bwp=calloc(1,sizeof(*bwp)); + bwp=calloc(1,sizeof(*bwp)); + } bwp->bwp_Id=1; bwp->bwp_Common=calloc(1,sizeof(*bwp->bwp_Common)); // copy common BWP size from initial BWP except for bandwdith @@ -577,8 +589,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,pdschi); } - bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated)); - + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated)); + } bwp->bwp_Dedicated->pdcch_Config=calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config)); bwp->bwp_Dedicated->pdcch_Config->present = NR_SetupRelease_PDCCH_Config_PR_setup; bwp->bwp_Dedicated->pdcch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup)); @@ -626,113 +639,30 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToReleaseList = NULL; - bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config)); + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated->pdsch_Config = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config)); bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup)); - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present= NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); + } + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dataScramblingIdentityPDSCH = NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID0=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->scramblingID1=NULL; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL; - + if (!servingcellconfigdedicated) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=NULL; + } bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0; - //bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList)); -#if 0 - bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList)); - - NR_TCI_State_t*tcid0=calloc(1,sizeof(*tcid0)); - tcid0->tci_StateId=0; - tcid0->qcl_Type1.cell=NULL; - tcid0->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid0->qcl_Type1.bwp_Id)); - *tcid0->qcl_Type1.bwp_Id=1; - tcid0->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid0->qcl_Type1.referenceSignal.choice.csi_rs = 2; - tcid0->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid0); - - NR_TCI_State_t*tcid1=calloc(1,sizeof(*tcid1)); - tcid1->tci_StateId=0; - tcid1->qcl_Type1.cell=NULL; - tcid1->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid1->qcl_Type1.bwp_Id)); - *tcid1->qcl_Type1.bwp_Id=1; - tcid1->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid1->qcl_Type1.referenceSignal.choice.csi_rs = 6; - tcid1->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid1); - - NR_TCI_State_t*tcid2=calloc(1,sizeof(*tcid2)); - tcid2->tci_StateId=2; - tcid2->qcl_Type1.cell=NULL; - tcid2->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid2->qcl_Type1.bwp_Id)); - *tcid2->qcl_Type1.bwp_Id=1; - tcid2->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid2->qcl_Type1.referenceSignal.choice.csi_rs = 10; - tcid2->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid2); - - NR_TCI_State_t*tcid3=calloc(1,sizeof(*tcid3)); - tcid3->tci_StateId=3; - tcid3->qcl_Type1.cell=NULL; - tcid3->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid3->qcl_Type1.bwp_Id)); - *tcid3->qcl_Type1.bwp_Id=1; - tcid3->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid3->qcl_Type1.referenceSignal.choice.csi_rs = 14; - tcid3->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid3); - - NR_TCI_State_t*tcid4=calloc(1,sizeof(*tcid4)); - tcid4->tci_StateId=4; - tcid4->qcl_Type1.cell=NULL; - tcid4->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid4->qcl_Type1.bwp_Id)); - *tcid4->qcl_Type1.bwp_Id=1; - tcid4->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid4->qcl_Type1.referenceSignal.choice.csi_rs = 18; - tcid4->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid4); - - NR_TCI_State_t*tcid5=calloc(1,sizeof(*tcid5)); - tcid5->tci_StateId=5; - tcid5->qcl_Type1.cell=NULL; - tcid5->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid5->qcl_Type1.bwp_Id)); - *tcid5->qcl_Type1.bwp_Id=1; - tcid5->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid5->qcl_Type1.referenceSignal.choice.csi_rs = 22; - tcid5->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid5); - - NR_TCI_State_t*tcid6=calloc(1,sizeof(*tcid6)); - tcid6->tci_StateId=6; - tcid6->qcl_Type1.cell=NULL; - tcid6->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid6->qcl_Type1.bwp_Id)); - *tcid6->qcl_Type1.bwp_Id=1; - tcid6->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid6->qcl_Type1.referenceSignal.choice.csi_rs = 26; - tcid6->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid6); - - NR_TCI_State_t*tcid7=calloc(1,sizeof(*tcid7)); - tcid7->tci_StateId=7; - tcid7->qcl_Type1.cell=NULL; - tcid7->qcl_Type1.bwp_Id=calloc(1,sizeof(*tcid7->qcl_Type1.bwp_Id)); - *tcid7->qcl_Type1.bwp_Id=1; - tcid7->qcl_Type1.referenceSignal.present = NR_QCL_Info__referenceSignal_PR_csi_rs; - tcid7->qcl_Type1.referenceSignal.choice.csi_rs = 30; - tcid7->qcl_Type1.qcl_Type=NR_QCL_Info__qcl_Type_typeA; - ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList->list,tcid7); -#endif - - n_ssb = 0; NR_TCI_State_t *tcid[64]; for (int i=0;i<64;i++) { @@ -828,8 +758,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco *bwp->bwp_Dedicated->radioLinkMonitoringConfig->choice.setup->beamFailureDetectionTimer = NR_RadioLinkMonitoringConfig__beamFailureDetectionTimer_pbfd2; #endif - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list,bwp); - + if (!servingcellconfigdedicated) { + ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list,bwp); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id=1; @@ -837,26 +768,38 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->defaultDownlinkBWP_Id = 1; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig)); + + if (!servingcellconfigdedicated) { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig)); + } NR_BWP_UplinkDedicated_t *initialUplinkBWP = calloc(1,sizeof(*initialUplinkBWP)); secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP = initialUplinkBWP; initialUplinkBWP->pucch_Config = NULL; initialUplinkBWP->pusch_Config = calloc(1,sizeof(*initialUplinkBWP->pusch_Config)); initialUplinkBWP->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; - NR_PUSCH_Config_t *pusch_Config = calloc(1,sizeof(*pusch_Config)); + NR_PUSCH_Config_t *pusch_Config = NULL; + if (servingcellconfigdedicated) { + pusch_Config = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup; + } else { + pusch_Config = calloc(1,sizeof(*pusch_Config)); + } initialUplinkBWP->pusch_Config->choice.setup = pusch_Config; pusch_Config->txConfig=calloc(1,sizeof(*pusch_Config->txConfig)); *pusch_Config->txConfig= NR_PUSCH_Config__txConfig_codebook; pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA = NULL; - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + if (!servingcellconfigdedicated) { + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + } NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; NR_DMRS_UplinkConfig->dmrs_Type = NULL; NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = calloc(1,sizeof(*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition)); *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0; - NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; + if (!servingcellconfigdedicated) { + NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; + } NR_DMRS_UplinkConfig->maxLength=NULL; NR_DMRS_UplinkConfig->transformPrecodingDisabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingDisabled)); NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0 = NULL; @@ -903,7 +846,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pusch_Config->tp_pi2BPSK=NULL; /*------------------------------TRANSFORM PRECODING- -----------------------------------------------------------------------*/ - + uint8_t transform_precoding = NR_PUSCH_Config__transformPrecoder_disabled; // TBD: configure this from .conf file, Dedicated params cannot yet be configured in .conf file. @@ -918,20 +861,20 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco if (servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder != NULL) transform_precoding = NR_PUSCH_Config__transformPrecoder_enabled; } - else + else transform_precoding = *pusch_Config->transformPrecoder; - - + + if (transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled ) { /* Enable DMRS uplink config for transform precoding enabled */ NR_DMRS_UplinkConfig->transformPrecodingEnabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingEnabled)); NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity = NULL; - NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping = NULL; + NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceGroupHopping = NULL; NR_DMRS_UplinkConfig->transformPrecodingEnabled->sequenceHopping = NULL; - NR_DMRS_UplinkConfig->transformPrecodingEnabled->ext1 = NULL; + NR_DMRS_UplinkConfig->transformPrecodingEnabled->ext1 = NULL; LOG_I(RRC,"TRANSFORM PRECODING ENABLED......\n"); - + } /*----------------------------------------------------------------------------------------------------------------------------*/ @@ -992,8 +935,13 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceToAddModList->list,srs_res0); secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToReleaseList = NULL; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList)); - NR_BWP_Uplink_t *ubwp = calloc(1,sizeof(*ubwp)); + NR_BWP_Uplink_t *ubwp = NULL; + if (servingcellconfigdedicated) { + ubwp = servingcellconfigdedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList)); + ubwp = calloc(1,sizeof(*ubwp)); + } ubwp->bwp_Id=1; ubwp->bwp_Common = calloc(1,sizeof(*ubwp->bwp_Common)); // copy bwp_Common from Initial UL BWP except for bandwidth @@ -1006,7 +954,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ubwp->bwp_Common->pusch_ConfigCommon = servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; ubwp->bwp_Common->pucch_ConfigCommon = servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon; - ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated)); + if (!servingcellconfigdedicated) { + ubwp->bwp_Dedicated = calloc(1,sizeof(*ubwp->bwp_Dedicated)); + } ubwp->bwp_Dedicated->pucch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pucch_Config)); ubwp->bwp_Dedicated->pucch_Config->present = NR_SetupRelease_PUCCH_Config_PR_setup; NR_PUCCH_Config_t *pucch_Config = calloc(1,sizeof(*pucch_Config)); @@ -1136,11 +1086,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&pucch_Config->pucch_PowerControl->p0_Set->list,p00); pucch_Config->pucch_PowerControl->pathlossReferenceRSs = NULL; - // copy pusch_Config from dedicated initialBWP - ubwp->bwp_Dedicated->pusch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pusch_Config)); - ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; - ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config; - + if (!servingcellconfigdedicated) { + // copy pusch_Config from dedicated initialBWP + ubwp->bwp_Dedicated->pusch_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->pusch_Config)); + ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; + ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config; + } ubwp->bwp_Dedicated->configuredGrantConfig = NULL; ubwp->bwp_Dedicated->srs_Config = calloc(1,sizeof(*ubwp->bwp_Dedicated->srs_Config)); ubwp->bwp_Dedicated->srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup; @@ -1148,7 +1099,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ubwp->bwp_Dedicated->beamFailureRecoveryConfig = NULL; - ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); + if (!servingcellconfigdedicated) { + ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp); + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = 1; @@ -1300,7 +1253,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->servingCellMO=NULL; } + void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon, + NR_ServingCellConfig_t *servingcellconfigdedicated, NR_RRCReconfiguration_IEs_t *reconfig, NR_CellGroupConfig_t *secondaryCellGroup, int n_physical_antenna_ports, @@ -1311,7 +1266,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon // radioBearerConfig reconfig->radioBearerConfig=NULL; // secondaryCellGroup - fill_default_secondaryCellGroup(servingcellconfigcommon,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index); + fill_default_secondaryCellGroup(servingcellconfigcommon,servingcellconfigdedicated,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index); xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); char scg_buffer[1024]; @@ -1347,7 +1302,7 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig, drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); - *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_ms30; + *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 5ad6746696..e21859ded8 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -33,6 +33,7 @@ #include "rrc_defs.h" #include "rrc_proto.h" #include "assertions.h" +#include "rrc_vars.h" typedef uint32_t channel_t; @@ -50,7 +51,7 @@ nr_mac_rrc_data_ind_ue( AssertFatal( nr_rrc_ue_decode_NR_BCCH_BCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-BCH error!\n"); break; case NR_BCCH_DL_SCH: - AssertFatal( nr_rrc_ue_decode_NR_SIB1_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len) == 0, "UE decode BCCH-DLSCH error!\n"); + AssertFatal( nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id, gNB_index, (uint8_t*)pduP, pdu_len, 0, 0) == 0, "UE decode BCCH-DL-SCH error!\n"); break; default: break; @@ -59,13 +60,36 @@ nr_mac_rrc_data_ind_ue( return(0); } -int8_t mac_rrc_nr_data_req_ue(const module_id_t Mod_idP, +int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, const int CC_id, + const uint8_t gNB_id, const frame_t frameP, const rb_id_t Srb_id, - uint8_t *const buffer_pP ){ + uint8_t *buffer_pP){ - // todo + switch(Srb_id){ + + case CCCH: + + // TODO: Enable timer T300 + //NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_active = 1; + //NR_UE_rrc_inst[Mod_idP].Info[gNB_id].T300_cnt = 0; + + LOG_D(NR_RRC, "nr_mac_rrc_data_req_ue: Payload size = %i\n", NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size); + memcpy(buffer_pP, (uint8_t*)NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.Payload, NR_UE_rrc_inst[Mod_idP].Srb0[gNB_id].Tx_buffer.payload_size); + for(int i = 0; imodule_id].MBMS_flag < 3) // see -Q option if (AMF_MODE_ENABLED) { - rrc_ue_generate_RRCSetupRequest( ctxt_pP, gNB_index ); + nr_rrc_ue_generate_RRCSetupRequest( ctxt_pP->module_id, gNB_index ); } if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State == NR_RRC_IDLE) { @@ -1029,205 +1041,120 @@ int nr_decode_SI( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index return 0; } -int nr_decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index, const uint8_t rsrq, const uint8_t rsrp ) { - NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN ); - LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id ); - const int n = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; - for (int i = 0; i < n; ++i) { - NR_PLMN_Identity_t *PLMN_identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[i]->plmn_IdentityList.list.array[0]; - int mccdigits = PLMN_identity->mcc->list.count; - int mncdigits = PLMN_identity->mnc.list.count; +int8_t check_requested_SI_List(module_id_t module_id, BIT_STRING_t requested_SI_List, NR_SIB1_t sib1) { - int mcc; - if (mccdigits == 2) { - mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; - } else { - mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; + if(sib1.si_SchedulingInfo) { + + bool SIB_to_request[32] = {}; + + LOG_D(RRC, "SIBs broadcasting: "); + for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { + printf("SIB%li ", sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type + 2); } + printf("\n"); - int mnc; - if (mncdigits == 2) { - mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; - } else { - mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; - } + LOG_D(RRC, "SIBs needed by UE: "); + for(int j = 0; j < 8*requested_SI_List.size; j++) { + if( ((requested_SI_List.buf[j/8]>>(j%8))&1) == 1) { - LOG_I( RRC, "PLMN %d MCC %0*d, MNC %0*d\n", i + 1, mccdigits, mcc, mncdigits, mnc); - // search internal table for provider name - int plmn_ind = 0; + printf("SIB%i ", j + 2); - while (plmn_data[plmn_ind].mcc > 0) { - if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { - LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); - break; - } - - plmn_ind++; - } - } - LOG_I( RRC, "TAC 0x%04x\n", - ((sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->size == 2)?((sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->buf[0]<<8) + sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode->buf[1]):0)); - LOG_I( RRC, "cellReservedForOperatorUse : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse, - nr_SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) ); - - LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n", - BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity ), - sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[0], - sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[1], - sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[2], - sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.buf[3] >> sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity.bits_unused); - //LOG_I( RRC, "cellAccessRelatedInfo.cellBarred : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.cellBarred, SIBbarred(sib1->cellAccessRelatedInfo.cellBarred) ); - //LOG_I( RRC, "cellAccessRelatedInfo.intraFreqReselection : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.intraFreqReselection, SIBallowed(sib1->cellAccessRelatedInfo.intraFreqReselection) ); - //LOG_I( RRC, "cellAccessRelatedInfo.csg_Indication : %d\n", sib1->cellAccessRelatedInfo.csg_Indication ); - - //if (sib1->cellAccessRelatedInfo.csg_Identity) - // LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity : %"PRIu32"\n", BIT_STRING_to_uint32(sib1->cellAccessRelatedInfo.csg_Identity) ); - //else - // LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity : not defined\n" ); - - LOG_I( RRC, "cellSelectionInfo.q_RxLevMin : %ld\n", sib1->cellSelectionInfo->q_RxLevMin ); - - if (sib1->cellSelectionInfo->q_RxLevMinOffset) - LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset : %ld\n", *sib1->cellSelectionInfo->q_RxLevMinOffset ); - else - LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset : not defined\n" ); - - //if (sib1->p_Max) - // LOG_I( RRC, "p_Max : %ld\n", *sib1->p_Max ); - //else - // LOG_I( RRC, "p_Max : not defined\n" ); - - //LOG_I( RRC, "freqBandIndicator : %ld\n", sib1->freqBandIndicator ); - - if (sib1->si_SchedulingInfo->schedulingInfoList.list.count > 0) { - for (int i=0; isi_SchedulingInfo->schedulingInfoList.list.count; i++) { - LOG_I( RRC, "si_Periodicity[%d] : %s\n", i, SIBPeriod[min(sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->si_Periodicity,7)]); - - if (sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count > 0) { - char temp[32 * sizeof(SIBType[0])] = {0}; // maxSIB==32 - - for (int j=0; jsi_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count; j++) { - sprintf( temp + j*sizeof(SIBType[0]), "%*s ", (int)sizeof(SIBType[0])-1, SIBType[min(sib1->si_SchedulingInfo->schedulingInfoList.list.array[i]->sib_MappingInfo.list.array[0]->type,11)] ); + SIB_to_request[j] = true; + for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { + if(sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type == j) { + SIB_to_request[j] = false; + break; + } } - LOG_I( RRC, "siSchedulingInfoSIBType[%d] : %s\n", i, temp ); + } + } + printf("\n"); + + LOG_D(RRC, "SIBs to request by UE: "); + bool do_ra = false; + for(int j = 0; j < 8*requested_SI_List.size; j++) { + if(SIB_to_request[j]) { + printf("SIB%i ", j + 2); + do_ra = true; + } + } + printf("\n"); + + if(do_ra) { + + NR_UE_rrc_inst[module_id].ra_trigger = REQUEST_FOR_OTHER_SI; + get_softmodem_params()->do_ra = 1; + + if(sib1.si_SchedulingInfo->si_RequestConfig) { + LOG_D(RRC, "Trigger contention-free RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger); } else { - LOG_I( RRC, "mapping list %d is null\n", i ); + LOG_D(RRC, "Trigger contention-based RA procedure (ra_trigger = %i)\n", NR_UE_rrc_inst[module_id].ra_trigger); } + } - } else { - LOG_E( RRC, "siSchedulingInfoPeriod[0] : PROBLEM!!!\n" ); - return -1; + } - if (sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon) { - //TODO - } - - LOG_I( RRC, "siWindowLength : %s\n", siWindowLength[min(sib1->si_SchedulingInfo->si_WindowLength,8)] ); - //LOG_I( RRC, "systemInfoValueTag : %ld\n", sib1->systemInfoValueTag ); - NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIperiod = siPeriod_int[sib1->si_SchedulingInfo->schedulingInfoList.list.array[0]->si_Periodicity]; - NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIwindowsize = siWindowLength_int[sib1->si_SchedulingInfo->si_WindowLength]; - LOG_I( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params gNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n", - ctxt_pP->module_id, gNB_index, ctxt_pP->module_id ); - //rrc_mac_config_req_ue - LOG_I(RRC,"Setting SIStatus bit 0 to 1\n"); - NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus = 1; - //NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag; - - if (AMF_MODE_ENABLED) { - int cell_valid = 0; - - //if (sib1->cellAccessRelatedInfo.cellBarred == LTE_SystemInformationBlockType1__cellAccessRelatedInfo__cellBarred_notBarred) { - /* Cell is not barred */ - int plmn; - int plmn_number; - plmn_number = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; - - /* Compare requested PLMN and PLMNs from SIB1*/ - for (plmn = 0; plmn < plmn_number; plmn++) { - NR_PLMN_Identity_t *plmn_Identity; - plmn_Identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[plmn]->plmn_IdentityList.list.array[0]; - - if ( - ( - (plmn_Identity->mcc == NULL) - || - ( - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit1 == *(plmn_Identity->mcc->list.array[0])) && - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit2 == *(plmn_Identity->mcc->list.array[1])) && - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit3 == *(plmn_Identity->mcc->list.array[2])) - ) - ) - && - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit1 == *(plmn_Identity->mnc.list.array[0])) - && - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit2 == *(plmn_Identity->mnc.list.array[1])) - && - ( - ((NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == 0xf) && (plmn_Identity->mnc.list.count == 2)) - || - (NR_UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == *(plmn_Identity->mnc.list.array[2])) - ) - ) { - /* PLMN match, send a confirmation to NAS */ - MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CELL_SELECTION_CNF); - NAS_CELL_SELECTION_CNF (msg_p).errCode = AS_SUCCESS; - NAS_CELL_SELECTION_CNF (msg_p).cellID = BIT_STRING_to_uint32(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellIdentity); - NAS_CELL_SELECTION_CNF (msg_p).tac = BIT_STRING_to_uint16(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->trackingAreaCode); - NAS_CELL_SELECTION_CNF (msg_p).rat = 0xFF; - NAS_CELL_SELECTION_CNF (msg_p).rsrq = rsrq; - NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp; - itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); - cell_valid = 1; - NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity = plmn + 1; - break; - } - } - //} - - if (cell_valid == 0) { - /* Cell can not be used, ask PHY to try the next one */ - MessageDef *msg_p; - msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, PHY_FIND_NEXT_CELL_REQ); - itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); - LOG_E(RRC, - "Synched with a cell, but PLMN doesn't match our SIM " - "(selected_plmn_identity %ld), the message PHY_FIND_NEXT_CELL_REQ " - "is sent but lost in current UE implementation!\n", - NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_OUT ); return 0; } -int nr_decode_BCCH_DLSCH_Message( - const protocol_ctxt_t *const ctxt_pP, - const uint8_t gNB_index, - uint8_t *const Sdu, - const uint8_t Sdu_len, - const uint8_t rsrq, - const uint8_t rsrp ) { +int8_t nr_rrc_ue_generate_ra_msg(module_id_t module_id, uint8_t gNB_index) { + + switch(NR_UE_rrc_inst[module_id].ra_trigger){ + case INITIAL_ACCESS_FROM_RRC_IDLE: + // After SIB1 is received, prepare RRCConnectionRequest + nr_rrc_ue_generate_RRCSetupRequest(module_id,gNB_index); + break; + case RRC_CONNECTION_REESTABLISHMENT: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case DURING_HANDOVER: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case NON_SYNCHRONISED: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case TRANSITION_FROM_RRC_INACTIVE: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case TO_ESTABLISH_TA: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case REQUEST_FOR_OTHER_SI: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + case BEAM_FAILURE_RECOVERY: + AssertFatal(1==0, "ra_trigger not implemented yet!\n"); + break; + default: + AssertFatal(1==0, "Invalid ra_trigger value!\n"); + break; + } + + return 0; +} + +int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message( + module_id_t module_id, + const uint8_t gNB_index, + uint8_t *const Sdu, + const uint8_t Sdu_len, + const uint8_t rsrq, + const uint8_t rsrp) { + NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; - NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; + NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN ); - if (((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 1) && // SIB1 received - (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count)) { + if (((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 1) && // SIB1 received + (NR_UE_rrc_inst[module_id].Info[gNB_index].SIcnt == sib1->si_SchedulingInfo->schedulingInfoList.list.count)) { // to prevent memory bloating VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); return 0; } - nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR ); - - if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message ); - } + nr_rrc_set_sub_state( module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR ); asn_dec_rval_t dec_rval = uper_decode_complete( NULL, &asn_DEF_NR_BCCH_DL_SCH_Message, @@ -1235,11 +1162,15 @@ int nr_decode_BCCH_DLSCH_Message( (const void *)Sdu, Sdu_len ); + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message ); + } + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E( RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", - ctxt_pP->module_id, + LOG_E( NR_RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", + module_id, dec_rval.consumed ); - log_dump(RRC, Sdu, Sdu_len, LOG_DUMP_CHAR," Received bytes:\n" ); + log_dump(NR_RRC, Sdu, Sdu_len, LOG_DUMP_CHAR," Received bytes:\n" ); // free the memory SEQUENCE_free( &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); @@ -1249,35 +1180,53 @@ int nr_decode_BCCH_DLSCH_Message( if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) { switch (bcch_message->message.choice.c1->present) { case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1: - if ((ctxt_pP->frame % 2) == 0) { - // even frame - if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 0) { - NR_SIB1_t *sib1 = NR_UE_rrc_inst[ctxt_pP->module_id].sib1[gNB_index]; - memcpy( (void *)sib1, - (void *)bcch_message->message.choice.c1->choice.systemInformationBlockType1, - sizeof(NR_SIB1_t) ); - LOG_D( RRC, "[UE %"PRIu8"] Decoding First SIB1\n", ctxt_pP->module_id ); - nr_decode_SIB1( ctxt_pP, gNB_index, rsrq, rsrp ); + if ((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 0) { + NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; + if(sib1 != NULL){ + SEQUENCE_free(&asn_DEF_NR_SIB1, (void *)sib1, 1 ); + } + + sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; + if (*(int64_t*)sib1 != 1) { + NR_UE_rrc_inst[module_id].sib1[gNB_index] = sib1; + if( g_log->log_component[NR_RRC].level >= OAILOG_DEBUG ) { + xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) NR_UE_rrc_inst[module_id].sib1[gNB_index]); + } + LOG_I(NR_RRC, "SIB1 decoded\n"); + + // FIXME: improve condition for the RA trigger + // Check for on-demand not broadcasted SI + check_requested_SI_List(module_id, NR_UE_rrc_inst[module_id].requested_SI_List, *sib1); + if( nr_rrc_get_state(module_id) == RRC_STATE_IDLE_NR ) { + NR_UE_rrc_inst[module_id].ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE; + // TODO: remove flag after full RA procedures implemented + get_softmodem_params()->do_ra = 1; + } + nr_rrc_ue_generate_ra_msg(module_id,gNB_index); + } else { + LOG_E(NR_RRC, "SIB1 not decoded\n"); } } - break; case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: - if ((NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].SIStatus&1) == 1) { + if ((NR_UE_rrc_inst[module_id].Info[gNB_index].SIStatus&1) == 1) { + LOG_W(NR_RRC, "Decoding SI not implemented yet\n"); + // TODO: Decode SI + /* // SIB1 with schedulingInfoList is available - NR_SystemInformation_t *si = NR_UE_rrc_inst[ctxt_pP->module_id].si[gNB_index]; + NR_SystemInformation_t *si = NR_UE_rrc_inst[module_id].si[gNB_index]; + memcpy( si, bcch_message->message.choice.c1->choice.systemInformation, sizeof(NR_SystemInformation_t) ); - LOG_I( RRC, "[UE %"PRIu8"] Decoding SI for frameP %"PRIu32"\n", - ctxt_pP->module_id, - ctxt_pP->frame ); + LOG_I(NR_RRC, "[UE %"PRIu8"] Decoding SI\n", module_id); nr_decode_SI( ctxt_pP, gNB_index ); - //if (nfapi_mode == 3) - //UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1; - } + if (nfapi_mode == 3) + UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1; + */ + } break; case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: @@ -1286,10 +1235,10 @@ int nr_decode_BCCH_DLSCH_Message( } } - if (nr_rrc_get_sub_state(ctxt_pP->module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) { + if (nr_rrc_get_sub_state(module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) { //if ( (NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL) || (!AMF_MODE_ENABLED)) { - rrc_ue_generate_RRCSetupRequest(ctxt_pP, 0); - nr_rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_CONNECTING ); + nr_rrc_ue_generate_RRCSetupRequest(module_id, 0); + nr_rrc_set_sub_state( module_id, RRC_SUB_STATE_IDLE_CONNECTING ); //} } @@ -1489,41 +1438,6 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB return rval; } -/*brief decode SIB1 message*/ -int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { - - NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; - - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_BCCH_DL_SCH_Message, - (void **)&bcch_message, - (const void *)bufferP, - buffer_len); - - if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { - LOG_D(RRC,"NR_BCCH_DL_SCH decode error\n"); - SEQUENCE_free( &asn_DEF_NR_BCCH_DL_SCH_Message, (void *)bcch_message, 1 ); - return -1; - } - else { - NR_SIB1_t *sib1 = NR_UE_rrc_inst[module_id].sib1[gNB_index]; - if(sib1 != NULL){ - SEQUENCE_free(&asn_DEF_NR_BCCH_BCH_Message, (void *)sib1, 1 ); - } - sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; - if (*(int64_t*)sib1 != 1) { - LOG_I(RRC, "SIB1 decoded\n"); - if( g_log->log_component[RRC].level >= OAILOG_DEBUG ) - xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1); - } - else - LOG_E(PHY, "sib1 is starting by 8 times 0\n"); - } - - return 0; -} - - // from NR SRB3 int8_t nr_rrc_ue_decode_NR_DL_DCCH_Message( const module_id_t module_id, @@ -1784,10 +1698,10 @@ nr_rrc_ue_process_securityModeCommand( } //----------------------------------------------------------------------------- -void rrc_ue_generate_RRCSetupRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ) { +void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) { uint8_t i=0,rv[6]; - if(NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size ==0) { + if(NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size ==0) { // Get RRCConnectionRequest, fill random for now // Generate random byte stream for contention resolution for (i=0; i<6; i++) { @@ -1801,16 +1715,16 @@ void rrc_ue_generate_RRCSetupRequest( const protocol_ctxt_t *const ctxt_pP, cons } LOG_T(NR_RRC,"\n"); - NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size = - do_RRCSetupRequest( - ctxt_pP->module_id, - (uint8_t *)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload, - rv); - LOG_I(NR_RRC,"[UE %d] : Frame %d, Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, eNB %d)\n", - ctxt_pP->module_id, ctxt_pP->frame, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index); + NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size = + do_RRCSetupRequest( + module_id, + (uint8_t *)NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.Payload, + rv); + LOG_I(NR_RRC,"[UE %d] : Logical Channel UL-CCCH (SRB0), Generating RRCSetupRequest (bytes %d, gNB %d)\n", + module_id, NR_UE_rrc_inst[module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index); - for (i=0; imodule_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) { - LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload[i]); + for (i=0; imcc, instance_p->mnc, instance_p->mnc_digit_length ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr, freq_band); switch (instance_p->N_RB_DL[i]) { + case 24: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb24; + break; case 32: servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb32; break; diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index f0e0fa9c23..1fb28ea05b 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -536,6 +536,14 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, return -1; } + if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) || + (x2ap_eNB_data->state == X2AP_ENB_STATE_READY)) + + { + X2AP_ERROR("Received Unexpexted X2 Setup Response Message\n"); + return -1; + } + X2AP_DEBUG("Received a new X2 setup response\n"); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse, @@ -662,6 +670,14 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, return -1; } + if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) || + (x2ap_eNB_data->state == X2AP_ENB_STATE_READY)) + + { + X2AP_ERROR("Received Unexpexted X2 Setup Failure Message\n"); + return -1; + } + X2AP_DEBUG("Received a new X2 setup failure\n"); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupFailure_IEs_t, ie, x2SetupFailure, @@ -730,6 +746,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true); if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -750,7 +767,11 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, //measResultListEUTRA.list.array[ncell_index]->physCellId; X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, X2AP_ProtocolIE_ID_id_GUMMEI_ID, true); - + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return -1; + } TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, X2AP_HANDOVER_REQ(msg).ue_gummei.mcc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len); OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code); @@ -761,6 +782,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -872,6 +894,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -882,6 +905,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -912,6 +936,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n", __FILE__, __LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; }else{ if (ie->value.choice.E_RABs_Admitted_List.list.count > 0) { @@ -959,6 +984,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck, X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return -1; + } + X2AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer; if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s */) @@ -1012,6 +1043,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -1022,6 +1054,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c index 4769380d18..847002ab44 100644 --- a/openair3/GTPV1-U/gtpv1u_eNB.c +++ b/openair3/GTPV1-U/gtpv1u_eNB.c @@ -1211,7 +1211,7 @@ int gtpv1u_eNB_init(void) { //gtpv1u_data_g.udp_data; RC.gtpv1u_data_g->seq_num = 0; RC.gtpv1u_data_g->restart_counter = 0; - + RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up = 0; /* Initializing GTPv1-U stack */ if ((rc = nwGtpv1uInitialize(&RC.gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) { LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc); diff --git a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c index 8ac43cf7b1..637d930226 100644 --- a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c +++ b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c @@ -190,7 +190,6 @@ int decode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint default: errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI; LOG_TRACE(WARNING, "DECODE_UNEXPECTED_IEI %x (4 bits)", ieiDecoded); - AssertFatal(0, " "); return TLV_DECODE_UNEXPECTED_IEI; } } diff --git a/openair3/NAS/COMMON/IES/SupportedCodecList.c b/openair3/NAS/COMMON/IES/SupportedCodecList.c index 3a69eee366..15a2fecaa0 100644 --- a/openair3/NAS/COMMON/IES/SupportedCodecList.c +++ b/openair3/NAS/COMMON/IES/SupportedCodecList.c @@ -43,13 +43,17 @@ int decode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t CHECK_LENGTH_DECODER(len - decoded, ielen); supportedcodeclist->systemidentification = *(buffer + decoded); decoded++; + ielen--; supportedcodeclist->lengthofbitmap = *(buffer + decoded); decoded++; + ielen--; //IES_DECODE_U16(supportedcodeclist->codecbitmap, *(buffer + decoded)); IES_DECODE_U16(buffer, decoded, supportedcodeclist->codecbitmap); + ielen=ielen -2; #if defined (NAS_DEBUG) dump_supported_codec_list_xml(supportedcodeclist, iei); #endif + decoded = decoded + ielen; return decoded; } int encode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t iei, uint8_t *buffer, uint32_t len) diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.c b/openair3/NAS/UE/EMM/SAP/emm_as.c index 99a3763dea..10b118eac0 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_as.c +++ b/openair3/NAS/UE/EMM/SAP/emm_as.c @@ -443,14 +443,14 @@ static int _emm_as_data_ind(nas_user_t *user, const emm_as_data_t *msg, int *emm EPS_MOBILITY_MANAGEMENT_MESSAGE) { /* Process EMM data */ rc = _emm_as_recv(user, plain_msg, bytes, emm_cause); + free(plain_msg); } else if (header.protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) { const OctetString data = {bytes, (uint8_t *)plain_msg}; /* Foward ESM data to EPS session management */ rc = lowerlayer_data_ind(user, &data); + free(plain_msg); } - - free(plain_msg); } } else { /* Process successfull lower layer transfer indication */ diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c index 67bfaf784e..b27270fadc 100644 --- a/openair3/NAS/UE/EMM/SecurityModeControl.c +++ b/openair3/NAS/UE/EMM/SecurityModeControl.c @@ -296,16 +296,16 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, else { /* Setup EMM cause code */ emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED; - - /* Release security mode control internal data */ - if (security_data->kenb.value) { - free(security_data->kenb.value); - security_data->kenb.value = NULL; - security_data->kenb.length = 0; - } } } + /* Release security mode control internal data */ + if (security_data->kenb.value) { + free(security_data->kenb.value); + security_data->kenb.value = NULL; + security_data->kenb.length = 0; + } + /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h index 77d03f4ae4..efac0201a3 100644 --- a/openair3/S1AP/s1ap_common.h +++ b/openair3/S1AP/s1ap_common.h @@ -106,7 +106,12 @@ extern int asn1_xer_print; if (ie == NULL ) { \ S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\ } \ - if (mandatory) DevAssert(ie != NULL); \ + if (mandatory) { \ + if (ie == NULL) { \ + S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\ + return -1; \ + } \ + } \ } while(0) /** \brief Function callback prototype. **/ diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 31ea3359da..e528c9e53e 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -73,6 +73,42 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); +static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p); +void s1ap_eNB_timer_expired(instance_t instance, + timer_has_expired_t *msg_p); + +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id) +{ + uint32_t *timeoutArg=NULL; + int ret=0; + timeoutArg=malloc(sizeof(uint32_t)); + *timeoutArg=timer_kind; + ret=timer_setup(interval_sec, + interval_us, + task_id, + instance, + type, + (void*)timeoutArg, + timer_id); + return ret; +} + +int s1ap_timer_remove(long timer_id) +{ + int ret; + ret=timer_remove(timer_id); + return ret; +} + uint32_t s1ap_generate_eNB_id(void) { char *out; char hostname[50]; @@ -98,7 +134,7 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, MessageDef *message_p = NULL; sctp_new_association_req_t *sctp_new_association_req_p = NULL; s1ap_eNB_mme_data_t *s1ap_mme_data_p = NULL; - struct s1ap_eNB_mme_data_s *mme = NULL; +// struct s1ap_eNB_mme_data_s *mme = NULL; DevAssert(instance_p != NULL); DevAssert(mme_ip_address != NULL); message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ); @@ -114,51 +150,32 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, local_ip_addr, sizeof(*local_ip_addr)); S1AP_INFO("[eNB %ld] check the mme registration state\n",instance_p->instance); - mme = NULL; + /* Create new MME descriptor */ + s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); + DevAssert(s1ap_mme_data_p != NULL); + s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + s1ap_mme_data_p->assoc_id = -1; + s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; + memcpy(&s1ap_mme_data_p->mme_s1_ip, + mme_ip_address, + sizeof(*mme_ip_address)); + s1ap_mme_data_p->mme_port = mme_port; + for (int i = 0; i < broadcast_plmn_num; ++i) + s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; - if ( mme == NULL ) { - /* Create new MME descriptor */ - s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); - DevAssert(s1ap_mme_data_p != NULL); - s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); - sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; - s1ap_mme_data_p->assoc_id = -1; - s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; - memcpy(&s1ap_mme_data_p->mme_s1_ip, - mme_ip_address, - sizeof(*mme_ip_address)); - s1ap_mme_data_p->mme_port = mme_port; - for (int i = 0; i < broadcast_plmn_num; ++i) - s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; - - s1ap_mme_data_p->s1ap_eNB_instance = instance_p; - STAILQ_INIT(&s1ap_mme_data_p->served_gummei); - /* Insert the new descriptor in list of known MME - * but not yet associated. - */ - RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); - s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; - instance_p->s1ap_mme_nb ++; - instance_p->s1ap_mme_pending_nb ++; - } else if (mme->state == S1AP_ENB_STATE_WAITING) { - instance_p->s1ap_mme_pending_nb ++; - sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; - S1AP_INFO("[eNB %ld] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", - instance_p->instance, - mme->state, mme->cnx_id, - instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); - /*s1ap_mme_data_p->cnx_id = mme->cnx_id; - sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; - - s1ap_mme_data_p->assoc_id = -1; - s1ap_mme_data_p->s1ap_eNB_instance = instance_p; - */ - } else { - S1AP_WARN("[eNB %ld] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", - instance_p->instance, - mme->state, mme->cnx_id, - instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); - } + s1ap_mme_data_p->s1ap_eNB_instance = instance_p; + STAILQ_INIT(&s1ap_mme_data_p->served_gummei); + /* Insert the new descriptor in list of known MME + * but not yet associated. + */ + RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + memcpy( &(s1ap_mme_data_p->mme_ip_address), mme_ip_address, sizeof(net_ip_address_t) ); + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->sctp_req_cnt++; + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; + instance_p->s1ap_mme_pending_nb ++; itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); } @@ -196,10 +213,10 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->eNB_id = s1ap_register_eNB->eNB_id; new_instance->cell_type = s1ap_register_eNB->cell_type; new_instance->tac = s1ap_register_eNB->tac; - + memcpy(&new_instance->eNB_s1_ip, - &s1ap_register_eNB->enb_ip_address, - sizeof(s1ap_register_eNB->enb_ip_address)); + &s1ap_register_eNB->enb_ip_address, + sizeof(s1ap_register_eNB->enb_ip_address)); for (int i = 0; i < s1ap_register_eNB->num_plmn; i++) { new_instance->mcc[i] = s1ap_register_eNB->mcc[i]; @@ -207,6 +224,15 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->mnc_digit_length[i] = s1ap_register_eNB->mnc_digit_length[i]; } + memcpy( &(new_instance->enb_ip_address), &(s1ap_register_eNB->enb_ip_address), sizeof(net_ip_address_t) ); + new_instance->s1_setuprsp_wait_timer = s1ap_register_eNB->s1_setuprsp_wait_timer; + new_instance->s1_setupreq_wait_timer = s1ap_register_eNB->s1_setupreq_wait_timer; + new_instance->s1_setupreq_count = s1ap_register_eNB->s1_setupreq_count; + new_instance->sctp_req_timer = s1ap_register_eNB->sctp_req_timer; + new_instance->sctp_req_count = s1ap_register_eNB->sctp_req_count; + new_instance->sctp_in_streams = s1ap_register_eNB->sctp_in_streams; + new_instance->sctp_out_streams = s1ap_register_eNB->sctp_out_streams; + new_instance->num_plmn = s1ap_register_eNB->num_plmn; new_instance->default_drx = s1ap_register_eNB->default_drx; /* Add the new instance to the list of eNB (meaningfull in virtual mode) */ @@ -217,8 +243,12 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * s1ap_register_eNB->eNB_id); } - DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, - S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0); + if( s1ap_register_eNB->nb_mme > S1AP_MAX_NB_MME_IP_ADDRESS ) + { + S1AP_ERROR("Invalid MME number = %d\n ", s1ap_register_eNB->nb_mme); + s1ap_register_eNB->nb_mme = S1AP_MAX_NB_MME_IP_ADDRESS; + } + new_instance->s1ap_mme_nb = s1ap_register_eNB->nb_mme; /* Trying to connect to provided list of MME ip address */ for (index = 0; index < s1ap_register_eNB->nb_mme; index++) { @@ -250,28 +280,131 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { s1ap_eNB_instance_t *instance_p; s1ap_eNB_mme_data_t *s1ap_mme_data_p; + s1ap_eNB_ue_context_t *ue_p = NULL; + MessageDef *message_p = NULL; + uint32_t timer_kind = 0; + struct plmn_identity_s* plmnInfo; + struct served_group_id_s* groupInfo; + struct served_gummei_s* gummeiInfo; + struct mme_code_s* mmeCode; + int8_t cnt = 0; + unsigned enb_s1ap_id[NUMBER_OF_UE_MAX]; DevAssert(sctp_new_association_resp != NULL); instance_p = s1ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1, sctp_new_association_resp->ulp_cnx_id); DevAssert(s1ap_mme_data_p != NULL); - - if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", - sctp_new_association_resp->sctp_state, - instance, - sctp_new_association_resp->ulp_cnx_id); - s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); - return; + memset(enb_s1ap_id, 0, sizeof(enb_s1ap_id) ); + if( s1ap_mme_data_p->timer_id != S1AP_TIMERID_INIT ) { + s1ap_timer_remove( s1ap_mme_data_p->timer_id ); + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; } + + if( sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED ) { + RB_FOREACH(ue_p, s1ap_ue_map, &instance_p->s1ap_ue_head) { + if( ue_p->mme_ref == s1ap_mme_data_p ) { + if(cnt < NUMBER_OF_UE_MAX) { + enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id; + cnt++; + + message_p = NULL; + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); + + if( message_p != NULL ) { + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = ue_p->eNB_ue_s1ap_id; + + if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) { + S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); + } + } else { + S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); + } + }else{ + S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt); + } + } + } + for( ; cnt > 0 ; ) { + cnt--; + struct s1ap_eNB_ue_context_s *ue_context_p = NULL; + struct s1ap_eNB_ue_context_s *s1ap_ue_context_p = NULL; + ue_context_p = s1ap_eNB_get_ue_context(instance_p, (uint32_t)enb_s1ap_id[cnt]); + if (ue_context_p != NULL) { + s1ap_ue_context_p = RB_REMOVE(s1ap_ue_map, &instance_p->s1ap_ue_head, ue_context_p); + s1ap_eNB_free_ue_context(s1ap_ue_context_p); + } + } + s1ap_mme_data_p->mme_name = 0; + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->nextstream = 0; + s1ap_mme_data_p->in_streams = 0; + s1ap_mme_data_p->out_streams = 0; + s1ap_mme_data_p->assoc_id = -1; + + while (!STAILQ_EMPTY(&s1ap_mme_data_p->served_gummei)) { + gummeiInfo = STAILQ_FIRST(&s1ap_mme_data_p->served_gummei); + STAILQ_REMOVE_HEAD(&s1ap_mme_data_p->served_gummei, next); - /* Update parameters */ - s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; - s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; - s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; - /* Prepare new S1 Setup Request */ - s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p); + while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) { + plmnInfo = STAILQ_FIRST(&gummeiInfo->served_plmns); + STAILQ_REMOVE_HEAD(&gummeiInfo->served_plmns, next); + free(plmnInfo); + } + while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) { + groupInfo = STAILQ_FIRST(&gummeiInfo->served_group_ids); + STAILQ_REMOVE_HEAD(&gummeiInfo->served_group_ids, next); + free(groupInfo); + } + while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) { + mmeCode = STAILQ_FIRST(&gummeiInfo->mme_codes); + STAILQ_REMOVE_HEAD(&gummeiInfo->mme_codes, next); + free(mmeCode); + } + free(gummeiInfo); + } + + STAILQ_INIT(&s1ap_mme_data_p->served_gummei); + + if( s1ap_mme_data_p->state == S1AP_ENB_STATE_DISCONNECTED ) { + if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || + (instance_p->sctp_req_count == 0xffff) ) { + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | SCTP_REQ_WAIT; + + if( s1ap_timer_setup( instance_p->sctp_req_timer, 0, TASK_S1AP, instance_p->instance, + timer_kind, S1AP_TIMER_ONE_SHOT, NULL, &s1ap_mme_data_p->timer_id) < 0 ) { + S1AP_ERROR("Timer Start NG(SCTP retransmission wait timer) : MME=%d\n",s1ap_mme_data_p->cnx_id); + s1ap_sctp_req( instance_p, s1ap_mme_data_p ); + } + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + } else { + S1AP_ERROR("SCTP disconnection reception : MME = %d\n",s1ap_mme_data_p->cnx_id); + + if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || + (instance_p->sctp_req_count == 0xffff) ) { + s1ap_sctp_req( instance_p, s1ap_mme_data_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + } + } else { + /* Update parameters */ + s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; + s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; + s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; + /* Prepare new S1 Setup Request */ + s1ap_mme_data_p->s1_setupreq_cnt = 0; + s1ap_mme_data_p->sctp_req_cnt = 0; + if (s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p) == -1) { + S1AP_ERROR("s1ap eNB generate s1 setup request failed\n"); + return; + } + } } static @@ -282,13 +415,94 @@ void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { mme_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream, sctp_data_ind->buffer, sctp_data_ind->buffer_length); #else - s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, - sctp_data_ind->buffer, sctp_data_ind->buffer_length); + if (s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, + sctp_data_ind->buffer, sctp_data_ind->buffer_length) == -1) { + S1AP_ERROR("Failed to handle s1ap eNB message\n"); + } #endif result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } +void s1ap_eNB_timer_expired( + instance_t instance, + timer_has_expired_t *msg_p) +{ + uint32_t timer_kind = 0; + int16_t line_ind = 0; + s1ap_eNB_mme_data_t *mme_desc_p = NULL; + uint32_t timer_ind = 0; + s1ap_eNB_instance_t *instance_p = NULL; + long timer_id = S1AP_TIMERID_INIT; + + instance_p = s1ap_eNB_get_instance(instance); + if(msg_p->arg!=NULL){ + timer_kind = *((uint32_t*)msg_p->arg); + free(msg_p->arg); + }else{ + S1AP_ERROR("s1 timer timer_kind is NULL\n"); + return; + } + line_ind = (int16_t)(timer_kind & S1AP_LINEIND); + timer_id = msg_p->timer_id; + + if( (timer_kind & S1AP_MMEIND) == S1AP_MMEIND ) { + mme_desc_p = s1ap_eNB_get_MME(instance_p, -1, line_ind); + if(mme_desc_p != NULL) { + if( timer_id == mme_desc_p->timer_id ) { + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + timer_ind = timer_kind & S1AP_TIMERIND; + + switch(timer_ind) + { + case S1_SETRSP_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); + } + break; + } + case S1_SETREQ_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); + } + break; + } + case SCTP_REQ_WAIT: + { + if( (instance_p->sctp_req_count >= mme_desc_p->sctp_req_cnt) || + (instance_p->sctp_req_count == 0xffff) ) { + s1ap_sctp_req( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",line_ind); + } + break; + } + default: + { + S1AP_WARN("Invalid Timer indication\n"); + break; + } + } + } else { + S1AP_DEBUG("Unmatch timer id\n"); + return; + } + } else { + S1AP_WARN("Not applicable MME detected : connection id = %d\n", line_ind); + return; + } + } + return; +} + void s1ap_eNB_init(void) { S1AP_DEBUG("Starting S1AP layer\n"); s1ap_eNB_prepare_internal_data(); @@ -412,6 +626,13 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { } break; + case TIMER_HAS_EXPIRED: + { + s1ap_eNB_timer_expired(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &received_msg->ittiMsg.timer_has_expired); + } + break; + default: S1AP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); @@ -452,6 +673,7 @@ static int s1ap_eNB_generate_s1_setup_request( uint8_t *buffer = NULL; uint32_t len = 0; int ret = 0; + uint32_t timer_kind = 0; DevAssert(instance_p != NULL); DevAssert(s1ap_mme_data_p != NULL); s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; @@ -526,6 +748,17 @@ static int s1ap_eNB_generate_s1_setup_request( return -1; } + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETRSP_WAIT; + + if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->s1_setupreq_cnt++; + /* Non UE-Associated signalling -> stream = 0 */ s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); return ret; @@ -534,3 +767,55 @@ static int s1ap_eNB_generate_s1_setup_request( +static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p) +{ + MessageDef *message_p = NULL; + sctp_new_association_req_t *sctp_new_association_req_p = NULL; + + if( instance_p == NULL ) + { + S1AP_ERROR("Invalid instance_p\n"); + return -1; + } + + message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ); + sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; + sctp_new_association_req_p->port = S1AP_PORT_NUMBER; + sctp_new_association_req_p->ppid = S1AP_SCTP_PPID; + sctp_new_association_req_p->in_streams = instance_p->sctp_in_streams; + sctp_new_association_req_p->out_streams = instance_p->sctp_out_streams; + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + + if( s1ap_mme_data_p->mme_ip_address.ipv4 != 0 ) { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv4 != 0 ) { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } else { + S1AP_ERROR("Invalid IP Address Format V4(MME):V6\n"); + return -1; + } + } else { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv6 != 0 ) { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } else { + S1AP_ERROR("Invalid IP Address Format V6(MME):V4\n"); + return -1; + } + } + + itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); + + s1ap_mme_data_p->sctp_req_cnt++; + + return 0; +} diff --git a/openair3/S1AP/s1ap_eNB.h b/openair3/S1AP/s1ap_eNB.h index 2abbc53ec9..2183587214 100644 --- a/openair3/S1AP/s1ap_eNB.h +++ b/openair3/S1AP/s1ap_eNB.h @@ -30,6 +30,22 @@ #ifndef S1AP_ENB_H_ #define S1AP_ENB_H_ +#define S1AP_MMEIND 0x80000000 +#define S1AP_UEIND 0x00000000 +#define S1_SETRSP_WAIT 0x00010000 +#define S1_SETREQ_WAIT 0x00020000 +#define SCTP_REQ_WAIT 0x00030000 +#define S1AP_LINEIND 0x0000ffff +#define S1AP_TIMERIND 0x00ff0000 + +#define S1AP_TIMERID_INIT 0xffffffffffffffff + +typedef enum s1ap_timer_type_s { + S1AP_TIMER_PERIODIC, + S1AP_TIMER_ONE_SHOT, + S1AP_TIMER_TYPE_MAX, +} s1ap_timer_type_t; + typedef struct s1ap_eNB_config_s { // MME related params unsigned char mme_enabled; ///< MME enabled ? @@ -43,6 +59,7 @@ void *s1ap_eNB_process_itti_msg(void*); void s1ap_eNB_init(void); void *s1ap_eNB_task(void *arg); +int s1ap_timer_remove(long timer_id); uint32_t s1ap_generate_eNB_id(void); #endif /* S1AP_ENB_H_ */ diff --git a/openair3/S1AP/s1ap_eNB_decoder.c b/openair3/S1AP/s1ap_eNB_decoder.c index 4635946a05..14e4b49238 100644 --- a/openair3/S1AP/s1ap_eNB_decoder.c +++ b/openair3/S1AP/s1ap_eNB_decoder.c @@ -89,8 +89,6 @@ static int s1ap_eNB_decode_initiating_message(S1AP_S1AP_PDU_t *pdu) { default: S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage.procedureCode); - AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n", - (int)pdu->choice.initiatingMessage.procedureCode); return -1; } diff --git a/openair3/S1AP/s1ap_eNB_defs.h b/openair3/S1AP/s1ap_eNB_defs.h index d8a8da8001..ed0909d66e 100644 --- a/openair3/S1AP/s1ap_eNB_defs.h +++ b/openair3/S1AP/s1ap_eNB_defs.h @@ -165,6 +165,12 @@ typedef struct s1ap_eNB_mme_data_s { /* Only meaningfull in virtual mode */ struct s1ap_eNB_instance_s *s1ap_eNB_instance; + + uint32_t nb_calls; + net_ip_address_t mme_ip_address; + long timer_id; + uint16_t s1_setupreq_cnt; + uint16_t sctp_req_cnt; } s1ap_eNB_mme_data_t; typedef struct s1ap_eNB_instance_s { @@ -217,6 +223,14 @@ typedef struct s1ap_eNB_instance_s { /* Default Paging DRX of the eNB as defined in TS 36.304 */ paging_drx_t default_drx; + net_ip_address_t enb_ip_address; + uint16_t s1_setuprsp_wait_timer; + uint16_t s1_setupreq_wait_timer; + uint16_t s1_setupreq_count; + uint16_t sctp_req_timer; + uint16_t sctp_req_count; + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; } s1ap_eNB_instance_t; typedef struct { diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 370d34868b..9ee3287b94 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -38,6 +38,9 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB_handlers.h" #include "s1ap_eNB_decoder.h" +#include "s1ap_eNB_encoder.h" + +#include "s1ap_eNB_itti_messaging.h" #include "s1ap_eNB_ue_context.h" #include "s1ap_eNB_trace.h" @@ -109,6 +112,20 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as uint32_t stream, S1AP_S1AP_PDU_t *pdu); +static int s1ap_eNB_snd_s1_setup_request( + s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p); + +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id); + /* Handlers matrix. Only eNB related procedure present here */ s1ap_message_decoded_callback messages_callback[][3] = { { 0, 0, 0 }, /* HandoverPreparation */ @@ -260,6 +277,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_S1SetupFailure_t *container; S1AP_S1SetupFailureIEs_t *ie; s1ap_eNB_mme_data_t *mme_desc_p; + uint32_t interval_sec = 0; + uint32_t timer_kind = 0; + s1ap_eNB_instance_t *instance_p; + DevAssert(pdu != NULL); container = &pdu->choice.unsuccessfulOutcome.value.choice.S1SetupFailure; @@ -270,7 +291,7 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing " + S1AP_ERROR("[SCTP %d] Received S1 setup failure for non existing " "MME context\n", assoc_id); return -1; } @@ -278,6 +299,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, S1AP_ProtocolIE_ID_id_Cause,true); + if(ie == NULL) { + return -1; + } + if ((ie->value.choice.Cause.present == S1AP_Cause_PR_misc) && (ie->value.choice.Cause.choice.misc == S1AP_CauseMisc_unspecified)) { S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n"); @@ -285,8 +310,56 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n"); } - mme_desc_p->state = S1AP_ENB_STATE_WAITING; - s1ap_handle_s1_setup_message(mme_desc_p, 0); + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) { + s1ap_timer_remove( mme_desc_p->timer_id ); + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + } + instance_p = mme_desc_p->s1ap_eNB_instance; + if( ( instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + ( instance_p->s1_setupreq_count == 0xffff) ) { + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_TimeToWait, false); + if( ie != NULL ) { + switch(ie->value.choice.TimeToWait) + { + case S1AP_TimeToWait_v1s: + interval_sec = 1; + break; + case S1AP_TimeToWait_v2s: + interval_sec = 2; + break; + case S1AP_TimeToWait_v5s: + interval_sec = 5; + break; + case S1AP_TimeToWait_v10s: + interval_sec = 10; + break; + case S1AP_TimeToWait_v20s: + interval_sec = 20; + break; + case S1AP_TimeToWait_v60s: + interval_sec = 60; + break; + default: + interval_sec = instance_p->s1_setupreq_wait_timer; + break; + } + } else { + interval_sec = instance_p->s1_setupreq_wait_timer; + } + + timer_kind = mme_desc_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETREQ_WAIT; + + if( s1ap_timer_setup(interval_sec, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &mme_desc_p->timer_id) < 0 ) { + S1AP_ERROR("Timer Start NG(S1 Setup Request) : MME=%d\n",mme_desc_p->cnx_id); + s1ap_eNB_snd_s1_setup_request( instance_p, mme_desc_p ); + } + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",mme_desc_p->cnx_id); + } return 0; } @@ -314,9 +387,27 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, return -1; } + /* Set the capacity of this MME */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); + if(ie == NULL) { + return -1; + } + mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_ServedGUMMEIs, true); + if(ie == NULL) { + return -1; + } + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) + { + s1ap_timer_remove( mme_desc_p->timer_id ); + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + } + mme_desc_p->s1_setupreq_cnt = 0; + mme_desc_p->sctp_req_cnt = 0; /* The list of served gummei can contain at most 8 elements. * LTE related gummei is the first element in the list, i.e with an id of 0. */ @@ -368,13 +459,7 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next); } - - /* Set the capacity of this MME */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); - - mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; - + /* Optionaly set the mme name */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_MMEname, false); @@ -392,7 +477,6 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, */ mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++; - s1ap_handle_s1_setup_message(mme_desc_p, 0); return 0; } @@ -725,6 +809,9 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false); if (ie) { + if( ie->value.choice.CriticalityDiagnostics.procedureCode ) { + S1AP_WARN("Received S1 Error indication CriticalityDiagnostics procedureCode = %ld\n", *ie->value.choice.CriticalityDiagnostics.procedureCode); + } // TODO continue } @@ -807,9 +894,11 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, &(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl)); /* id-E-RABToBeSetupListCtxtSUReq */ } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, S1AP_ProtocolIE_ID_id_E_RABToBeSetupListCtxtSUReq, true); @@ -852,6 +941,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability; } /* for i... */ } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -865,6 +955,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms); } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -876,9 +967,10 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } - + /* id-NRUESecurityCapabilities */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false); @@ -891,7 +983,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0; } - + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; @@ -918,6 +1010,13 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, return -1; } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, + S1AP_ProtocolIE_ID_id_Cause, true); + if( ie == NULL ) { + S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(Cause)\n" ); + return -1; + } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_UE_S1AP_IDs, true); @@ -965,9 +1064,26 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, //#warning "TODO mapping mme_ue_s1ap_id enb_ue_s1ap_id?" case S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID: - mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID; - S1AP_ERROR("TO DO mapping mme_ue_s1ap_id enb_ue_s1ap_id"); - (void)mme_ue_s1ap_id; /* TODO: remove - it's to remove gcc warning about unused var */ + mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.mME_UE_S1AP_ID; + + RB_FOREACH(ue_desc_p, s1ap_ue_map, &mme_desc_p->s1ap_eNB_instance->s1ap_ue_head) + { + if( ue_desc_p->mme_ue_s1ap_id == mme_ue_s1ap_id ) + { + enb_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id; + + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); + + return 0; + } + } + S1AP_ERROR("[SCTP %d] Received UE context release command(mME_UE_S1AP_ID) for non " + "existing UE context 0x%06lx\n", + assoc_id, + mme_ue_s1ap_id); + return -1; case S1AP_UE_S1AP_IDs_PR_NOTHING: default: @@ -975,12 +1091,10 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, return -1; } } else { + S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(UE_S1AP_IDs)\n" ); return -1; } - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, - S1AP_ProtocolIE_ID_id_Cause, true); - /* TBD */ } static @@ -999,7 +1113,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.E_RABSetupRequest; if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non " "existing MME context\n", assoc_id); return -1; } @@ -1026,7 +1140,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance, enb_ue_s1ap_id)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non " "existing UE context 0x%06lx\n", assoc_id, enb_ue_s1ap_id); return -1; @@ -1099,6 +1213,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1119,13 +1234,6 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, // received Paging Message from MME S1AP_DEBUG("[SCTP %d] Received Paging Message From MME\n",assoc_id); - /* Paging procedure -> stream != 0 */ - if (stream == 0) { - LOG_W(S1AP,"[SCTP %d] Received Paging procedure on stream (%d)\n", - assoc_id, stream); - return -1; - } - if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { S1AP_ERROR("[SCTP %d] Received Paging for non " "existing MME context\n", assoc_id); @@ -1153,6 +1261,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code = 0; S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi = 0; } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1180,6 +1289,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, if(i != ie->value.choice.UEPagingID.choice.iMSI.size - 1) { /* invalid paging_p->uePagingID.choise.iMSI.buffer */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI error(i %d 0x0F)\n", assoc_id,i); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { @@ -1190,14 +1300,17 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length >= S1AP_IMSI_LENGTH) { /* invalid paging_p->uePagingID.choise.iMSI.size */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI.size(%d) is over IMSI length(%d)\n", assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length, S1AP_IMSI_LENGTH); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { /* of if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_iMSI) */ /* invalid paging_p->uePagingID.present */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.present(%d) is unknown\n", assoc_id, ie->value.choice.UEPagingID.present); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { /* of ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1230,6 +1343,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, return -1; } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1257,6 +1371,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, S1AP_PAGING_IND(message_p).tac[i]); } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1351,6 +1466,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, S1AP_E_RAB_MODIFY_RESP(message_p).e_rabs_failed[nb_of_e_rabs_failed].cause_value = S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id; } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1403,6 +1519,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else { /* of if (ie != NULL)*/ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1476,6 +1593,24 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_E_RAB_RELEASE_COMMAND); S1AP_E_RAB_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; S1AP_E_RAB_RELEASE_COMMAND(message_p).mme_ue_s1ap_id = mme_ue_s1ap_id; + /* id-E-RABToBeReleasedList */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count; + + for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) { + S1AP_E_RABItem_t *item_p; + item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem); + S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; + S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); + } + } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); + return -1; + } + /* id-NAS-PDU */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, S1AP_ProtocolIE_ID_id_NAS_PDU, false); @@ -1491,24 +1626,6 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0; S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL; } - - /* id-E-RABToBeReleasedList */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true); - - if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count; - - for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) { - S1AP_E_RABItem_t *item_p; - item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem); - S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; - S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); - } - } else { - return -1; - } - itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; } @@ -1533,7 +1650,6 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (stream == 0) { S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream (%d)\n", assoc_id, stream); - //return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { @@ -1550,6 +1666,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1572,6 +1689,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1589,6 +1707,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1602,14 +1721,10 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, false); if (ie) { - OCTET_STRING_TO_INT32 ( - &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL, - S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul - ); - OCTET_STRING_TO_INT32 ( - &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL, - S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl - ); + asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL, + &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul); + asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL, + &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl); } else { S1AP_WARN("UEAggregateMaximumBitrate not supported\n"); S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0; @@ -1688,9 +1803,8 @@ int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_ pathSwitchRequestFailure = &pdu->choice.unsuccessfulOutcome.value.choice.PathSwitchRequestFailure; if (stream != 0) { - S1AP_ERROR("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n", + S1AP_WARN("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n", assoc_id, stream); - return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { @@ -1754,3 +1868,144 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as return 0; } +//----------------------------------------------------------------------------- +/* +* eNB generate a S1 setup request towards MME +*/ +static int s1ap_eNB_snd_s1_setup_request( + s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p) +//----------------------------------------------------------------------------- +{ + S1AP_S1AP_PDU_t pdu; + S1AP_S1SetupRequest_t *out = NULL; + S1AP_S1SetupRequestIEs_t *ie = NULL; + S1AP_SupportedTAs_Item_t *ta = NULL; + S1AP_PLMNidentity_t *plmn = NULL; + uint8_t *buffer = NULL; + uint32_t len = 0; + int ret = 0; + uint32_t timer_kind = 0; + + DevAssert(instance_p != NULL); + DevAssert(s1ap_mme_data_p != NULL); + s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; + /* Prepare the S1AP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_S1Setup; + pdu.choice.initiatingMessage.criticality = S1AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_S1SetupRequest; + out = &pdu.choice.initiatingMessage.value.choice.S1SetupRequest; + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_Global_ENB_ID; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_Global_ENB_ID; + MCC_MNC_TO_PLMNID(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[0]], + instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[0]], + instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[0]], + &ie->value.choice.Global_ENB_ID.pLMNidentity); + ie->value.choice.Global_ENB_ID.eNB_ID.present = S1AP_ENB_ID_PR_macroENB_ID; + MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id, + &ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID); + S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0], + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1], + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (instance_p->eNB_name) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_eNBname; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_ENBname; + OCTET_STRING_fromBuf(&ie->value.choice.ENBname, instance_p->eNB_name, + strlen(instance_p->eNB_name)); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_SupportedTAs; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_SupportedTAs; + { + ta = (S1AP_SupportedTAs_Item_t *)calloc(1, sizeof(S1AP_SupportedTAs_Item_t)); + INT16_TO_OCTET_STRING(instance_p->tac, &ta->tAC); + { + for (int i = 0; i < s1ap_mme_data_p->broadcast_plmn_num; ++i) { + plmn = (S1AP_PLMNidentity_t *)calloc(1, sizeof(S1AP_PLMNidentity_t)); + MCC_MNC_TO_TBCD(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[i]], + instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[i]], + instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[i]], + plmn); + ASN_SEQUENCE_ADD(&ta->broadcastPLMNs.list, plmn); + } + } + ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAs.list, ta); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_DefaultPagingDRX; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_PagingDRX; + ie->value.choice.PagingDRX = instance_p->default_drx; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_CSG_IdList; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_CSG_IdList; + // ie->value.choice.CSG_IdList = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ +#if (S1AP_VERSION >= MAKE_VERSION(13, 0, 0)) + + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_UE_RetentionInformation; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_UE_RetentionInformation; + // ie->value.choice.UE_RetentionInformation = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_NB_IoT_DefaultPagingDRX; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_NB_IoT_DefaultPagingDRX; + // ie->value.choice.NB_IoT_DefaultPagingDRX = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + +#endif /* #if (S1AP_VERSION >= MAKE_VERSION(14, 0, 0)) */ + + if (s1ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + S1AP_ERROR("Failed to encode S1 setup request\n"); + return -1; + } + + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETRSP_WAIT; + + if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->s1_setupreq_cnt++; + + /* Non UE-Associated signalling -> stream = 0 */ + s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); + return ret; +} diff --git a/openair3/S1AP/s1ap_eNB_management_procedures.c b/openair3/S1AP/s1ap_eNB_management_procedures.c index fc7ae70e49..a870e975a2 100644 --- a/openair3/S1AP/s1ap_eNB_management_procedures.c +++ b/openair3/S1AP/s1ap_eNB_management_procedures.c @@ -95,23 +95,43 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME( { struct s1ap_eNB_mme_data_s temp; struct s1ap_eNB_mme_data_s *found; + struct s1ap_eNB_mme_data_s *mme_p; memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s)); temp.assoc_id = assoc_id; temp.cnx_id = cnx_id; - if (instance_p == NULL) { - STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, - s1ap_eNB_entries) { - found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); + if( cnx_id != 0 ) { + if (instance_p == NULL) { + STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, + s1ap_eNB_entries) { + found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); - if (found != NULL) { - return found; + if (found != NULL) { + return found; + } } + } else { + return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); } } else { - return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); + if (instance_p == NULL) { + STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, + s1ap_eNB_entries) { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + if( mme_p->assoc_id == assoc_id ) { + return mme_p; + } + } + } + } else { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + if( mme_p->assoc_id == assoc_id ) { + return mme_p; + } + } + } } return NULL; diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c index 919989897a..b55bc06e11 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c @@ -138,8 +138,8 @@ int s1ap_eNB_handle_nas_first_req( * identity, selects the MME with the highest capacity. */ mme_desc_p = s1ap_eNB_nnsf_select_mme( - instance_p, - s1ap_nas_first_req_p->establishment_cause); + instance_p, + s1ap_nas_first_req_p->establishment_cause); if (mme_desc_p) { S1AP_INFO("[eNB %ld] Chose MME '%s' (assoc_id %d) through highest relative capacity\n", @@ -358,10 +358,18 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.DownlinkNASTransport; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true); + if(ie == NULL) + { + return -1; + } mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true); + if(ie == NULL) + { + return -1; + } enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID; if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance, @@ -416,6 +424,10 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_NAS_PDU, true); + if(ie == NULL) + { + return -1; + } /* Forward the NAS PDU to RRC */ s1ap_eNB_itti_send_nas_downlink_ind(s1ap_eNB_instance->instance, ue_desc_p->ue_initial_id, @@ -494,9 +506,9 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_ ie->criticality = S1AP_Criticality_ignore; ie->value.present = S1AP_UplinkNASTransport_IEs__value_PR_EUTRAN_CGI; MCC_MNC_TO_PLMNID( - s1ap_eNB_instance_p->mcc[ue_context_p->selected_plmn_identity], - s1ap_eNB_instance_p->mnc[ue_context_p->selected_plmn_identity], - s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->selected_plmn_identity], + s1ap_eNB_instance_p->mcc[ue_context_p->mme_ref->broadcast_plmn_index[0]], + s1ap_eNB_instance_p->mnc[ue_context_p->mme_ref->broadcast_plmn_index[0]], + s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->mme_ref->broadcast_plmn_index[0]], &ie->value.choice.EUTRAN_CGI.pLMNidentity); //#warning "TODO get cell id from RRC" MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id, diff --git a/openair3/S1AP/s1ap_eNB_nnsf.c b/openair3/S1AP/s1ap_eNB_nnsf.c index 6319f6e054..a5a4e74734 100644 --- a/openair3/S1AP/s1ap_eNB_nnsf.c +++ b/openair3/S1AP/s1ap_eNB_nnsf.c @@ -36,15 +36,29 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB_nnsf.h" + +typedef struct MME_nnsf_inf { + struct s1ap_eNB_mme_data_s *mme_p; + uint64_t weight; +} MME_nnsf_inf_t; + struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, rrc_establishment_cause_t cause) { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - uint8_t current_capacity = 0; - + + uint16_t capacity_sum = 0; + MME_nnsf_inf_t mme_inf[10]; + int cnt; + int nb_mme = 0; + uint64_t weight = 0; + + memset(mme_inf, 0, sizeof(mme_inf)); + RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + capacity_sum = capacity_sum + mme_data_p->relative_mme_capacity; if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) { /* The association between MME and eNB is not ready for the moment, * go to the next known MME. @@ -69,7 +83,8 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, || (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) { continue; } - + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; /* At this point, the RRC establishment can be handled by the MME * even if it is in overload state. */ @@ -78,14 +93,27 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, continue; } } - - if (current_capacity < mme_data_p->relative_mme_capacity) { - /* We find a better MME, keep a reference to it */ - current_capacity = mme_data_p->relative_mme_capacity; - mme_highest_capacity_p = mme_data_p; - } } - + + if( nb_mme != 0 ) { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) { + mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; + mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); + } + mme_highest_capacity_p = mme_inf[0].mme_p; + weight = mme_inf[0].weight; + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) { + if( weight > mme_inf[cnt].weight ) { + mme_highest_capacity_p = mme_inf[cnt].mme_p; + weight = mme_inf[cnt].weight; + } + } + } else { + mme_highest_capacity_p = NULL; + } + if( mme_highest_capacity_p != NULL ) { + mme_highest_capacity_p->nb_calls++; + } return mme_highest_capacity_p; } @@ -96,8 +124,15 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - uint8_t current_capacity = 0; - + + uint16_t capacity_sum = 0; + MME_nnsf_inf_t mme_inf[10]; + int cnt; + int nb_mme = 0; + uint64_t weight = 0; + + memset(mme_inf, 0, sizeof(mme_inf)); + RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { struct served_gummei_s *gummei_p = NULL; struct plmn_identity_s *served_plmn_p = NULL; @@ -140,6 +175,8 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) { if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) && (served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) { + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; break; } } @@ -148,14 +185,27 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, } /* if we didn't find such a served PLMN, go on with the next MME */ if (!served_plmn_p) continue; - - if (current_capacity < mme_data_p->relative_mme_capacity) { - /* We find a better MME, keep a reference to it */ - current_capacity = mme_data_p->relative_mme_capacity; - mme_highest_capacity_p = mme_data_p; - } } + if( nb_mme != 0 ) { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) { + mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; + mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); + } + mme_highest_capacity_p = mme_inf[0].mme_p; + weight = mme_inf[0].weight; + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) { + if( weight > mme_inf[cnt].weight ) { + mme_highest_capacity_p = mme_inf[cnt].mme_p; + weight = mme_inf[cnt].weight; + } + } + } else { + mme_highest_capacity_p = NULL; + } + if( mme_highest_capacity_p != NULL ) { + mme_highest_capacity_p->nb_calls++; + } return mme_highest_capacity_p; } diff --git a/openair3/S1AP/s1ap_eNB_overload.c b/openair3/S1AP/s1ap_eNB_overload.c index 9358ae62bd..64d3fcdf65 100644 --- a/openair3/S1AP/s1ap_eNB_overload.c +++ b/openair3/S1AP/s1ap_eNB_overload.c @@ -62,8 +62,16 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id, S1AP_OverloadResponse_PR_overloadAction, S1AP_OverloadResponse_PR_overloadAction, 0, 0); } + else + { + return -1; + } /* Non UE-associated signalling -> stream 0 */ - DevCheck(stream == 0, stream, 0, 0); + if (stream != 0) { + S1AP_ERROR("[SCTP %d] Received s1 overload start on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { /* No MME context associated */ @@ -93,7 +101,11 @@ int s1ap_eNB_handle_overload_stop(uint32_t assoc_id, s1ap_eNB_mme_data_t *mme_desc_p; /* Non UE-associated signalling -> stream 0 */ - DevCheck(stream == 0, stream, 0, 0); + if (stream != 0) { + S1AP_ERROR("[SCTP %d] Received s1 overload stop on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { /* No MME context associated */ diff --git a/openair3/S1AP/s1ap_eNB_trace.c b/openair3/S1AP/s1ap_eNB_trace.c index 19f5059238..695eeb4ef8 100644 --- a/openair3/S1AP/s1ap_eNB_trace.c +++ b/openair3/S1AP/s1ap_eNB_trace.c @@ -121,6 +121,10 @@ int s1ap_eNB_handle_trace_start(uint32_t assoc_id, if (ie != NULL) { ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance, ie->value.choice.ENB_UE_S1AP_ID); + } + else + { + return -1; } if (ue_desc_p == NULL) { /* Could not find context associated with this eNB_ue_s1ap_id -> generate diff --git a/openair3/SCTP/sctp_default_values.h b/openair3/SCTP/sctp_default_values.h index 528ffb5a05..0f8f94dca9 100644 --- a/openair3/SCTP/sctp_default_values.h +++ b/openair3/SCTP/sctp_default_values.h @@ -24,8 +24,8 @@ #define SCTP_OUT_STREAMS (16) #define SCTP_IN_STREAMS (16) -#define SCTP_MAX_ATTEMPTS (2) -#define SCTP_TIMEOUT (5) +#define SCTP_MAX_ATTEMPTS (8) +#define SCTP_TIMEOUT (60000) #define SCTP_RECV_BUFFER_SIZE (8192) #endif /* SCTP_DEFAULT_VALUES_H_ */ diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index 2f732443be..af49c5c350 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -270,7 +270,7 @@ sctp_handle_new_association_req_multi( sctp_new_association_req_p->remote_address.ipv6_address); //close(sd); //return; - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error"); } SCTP_DEBUG("Converted ipv6 address %*s to network type\n", @@ -290,7 +290,7 @@ sctp_handle_new_association_req_multi( sctp_new_association_req_p->remote_address.ipv4_address); //close(sd); //return; - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error"); } SCTP_DEBUG("Converted ipv4 address %*s to network type\n", @@ -329,7 +329,7 @@ sctp_handle_new_association_req_multi( if (ns == -1) { perror("sctp_peeloff"); printf("sctp_peeloff: sd=%d assoc_id=%d\n", sd, assoc_id); - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: sctp_peeloff error"); } sctp_cnx = calloc(1, sizeof(*sctp_cnx)); @@ -943,10 +943,12 @@ sctp_eNB_read_from_socket( &sinfo, &flags); if (n < 0) { - if (errno == ENOTCONN) { + if( (errno == ENOTCONN) || (errno == ECONNRESET) || (errno == ETIMEDOUT) || (errno == ECONNREFUSED) ) + { itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd); SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd); + SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno); sctp_itti_send_association_resp( sctp_cnx->task_id, sctp_cnx->instance, -1, @@ -969,7 +971,7 @@ sctp_eNB_read_from_socket( if (!(flags & MSG_EOR)) { SCTP_ERROR("fatal: partial SCTP messages are not handled\n"); - exit(1); + exit_fun("fatal: partial SCTP messages are not handled" ); } if (flags & MSG_NOTIFICATION) { diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index dd29d01fae..61a742af65 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -1110,7 +1110,7 @@ extern "C" { case 46080000: //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 15; + openair0_cfg[0].tx_sample_advance = 65; openair0_cfg[0].tx_bw = 40e6; openair0_cfg[0].rx_bw = 40e6; break; @@ -1125,7 +1125,7 @@ extern "C" { case 15360000: //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 45; + openair0_cfg[0].tx_sample_advance = 40; openair0_cfg[0].tx_bw = 10e6; openair0_cfg[0].rx_bw = 10e6; break; diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c index daf0133af2..dcea69b9dd 100644 --- a/targets/ARCH/rfsimulator/stored_node.c +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -200,7 +200,10 @@ int main(int argc, char *argv[]) { int bufSize=100000; void *buff=malloc(bufSize); uint64_t timestamp=0; - const int blockSize=1000; + const int blockSize=1920; + + // If fileSize is not multiple of blockSize*4 then discard remaining samples + fileSize = (fileSize/(blockSize<<2))*(blockSize<<2); while (1) { //Rewind the file to loop on the samples diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf index 9e13d493a8..32de0aa4f5 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf @@ -225,14 +225,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( @@ -246,8 +247,15 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; # if_freq = 3700000000L; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf index 831f9c7978..307cf52cb3 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf @@ -225,14 +225,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( @@ -246,8 +247,15 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; clock_src = "external"; # if_freq = 3700000000L; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf new file mode 100644 index 0000000000..deed91c93c --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.PTRS.usrpx300.conf @@ -0,0 +1,331 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + + # downlinkConfigCommon + # frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 + initialDLBWPstartSymbolAndLength_3 = 57; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; + #prach_msg1_FDM + #0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; + #preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; + #powerRampingStep + # 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; + #ra_ReponseWindow + #1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; + #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR + #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; + #oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; + #ra_ContentionResolutionTimer + #(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; + #prach-RootSequenceIndex_PR + #1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + # restrictedSetConfig + # 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + + # pucch-ConfigCommon setup : + # pucchGroupHopping + # 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + # ssb_PositionsInBurs_BitmapPR + # 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + + # ssb_periodicityServingCell + # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + + # dmrs_TypeA_position + # 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + # Dedicated Serving Cell Configuration + servingCellConfigDedicated = ( + { + # DL PTRS related parameters. + # 3GPP TS 38.331 PTRS-DownlinkConfig + + # frequencyDensity value range: 1-276 + dl_ptrsFreqDensity0_0 = 25; + dl_ptrsFreqDensity1_0 = 75; + + # timeDensity value range: 0-29 + dl_ptrsTimeDensity0_0 = 2; + dl_ptrsTimeDensity1_0 = 4; + dl_ptrsTimeDensity2_0 = 10; + + # epre_Ratio + # 0 = "00", 1 = "01" in TS 38.214, table 4.1-2 + dl_ptrsEpreRatio_0 = 0; + + # resourceElementOffset + # 0 = offset01 1 = offset02, 2 = offset02 + # 3GPP TS 38.331 PTRS-DownlinkConfig; TS 38.211 sec. 7.4.1.2.2 + dl_ptrsReOffset_0 = 0; + + # UL PTRS related parameters. + # 3GPP TS 38.331 PTRS-UplinkConfig + + # frequencyDensity value range: 1-276 + ul_ptrsFreqDensity0_0 = 25; + ul_ptrsFreqDensity1_0 = 75; + + # timeDensity value range: 0-29 + ul_ptrsTimeDensity0_0 = 2; + ul_ptrsTimeDensity1_0 = 4; + ul_ptrsTimeDensity2_0 = 10; + + # resourceElementOffset + # 0 = offset01 1 = offset02, 2 = offset02 + # TS 38.331 PTRS-UplinkConfig; TS 38.211 sec. 6.4.1.2.2.1 + ul_ptrsReOffset_0 = 0; + + # maxNrofPorts + # 0 = n1, 1 = n2 + ul_ptrsMaxPorts_0 = 0; + + # ptrs-Power + # 0 = p00, 1 = p01, 2 = p10, 3 = p11 + #ul_ptrsPower_0 = 0; + } + ); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + sdr_addrs = "type=x300"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; +}; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index 760689f653..c77497dedd 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -226,15 +226,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - pusch_proc_threads = 8; - } + pusch_proc_threads = 8; + } ); RUs = ( diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf index d38fff4241..b3fdd79475 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf @@ -23,7 +23,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; - + servingCellConfigCommon = ( { #spCellConfigCommon @@ -135,18 +135,17 @@ gNBs = initialULBWPmappingType_0 = 1 # this is SS=0 L=11 initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 6; + + initialULBWPk2_1 = 6; initialULBWPmappingType_1 = 1; # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; - initialULBWPk2_2 = 7; + initialULBWPk2_2 = 7; initialULBWPmappingType_2 = 1; # this is SS=10 L=4 initialULBWPstartSymbolAndLength_2 = 52; - msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; @@ -227,14 +226,15 @@ MACRLCs = ( num_cc = 1; tr_s_preference = "local_L1"; tr_n_preference = "local_RRC"; - } + } ); L1s = ( - { + { num_cc = 1; tr_n_preference = "local_mac"; - } + pusch_proc_threads = 8; + } ); RUs = ( @@ -248,8 +248,15 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - #beamforming 1x4 matrix: - bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; clock_src = "external"; } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf new file mode 100644 index 0000000000..9f69849ace --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpb210.conf @@ -0,0 +1,292 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=b200"; + #"addr=192.168.18.207"; + #"addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf new file mode 100644 index 0000000000..56f07668d7 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpn300.conf @@ -0,0 +1,290 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf new file mode 100644 index 0000000000..687a188456 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.24PRB.usrpx300.conf @@ -0,0 +1,290 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sdr_addrs = "type=x300"; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf new file mode 100644 index 0000000000..12e4525454 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_24PRB.conf @@ -0,0 +1,306 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 12 PRBs@30kHz SCS + absoluteFrequencySSB = 640288; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 24; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 24; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6325; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -100; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.99"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "192.168.18.199"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.198/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.18.198/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "192.168.18.198/24"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + ## beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ## beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + #bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 4373f38e7b..d28427dbf3 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -75,17 +75,12 @@ gNBs = initialDLBWPk0_2 = 0; initialDLBWPmappingType_2 = 0; #this is SS=1,L=12 - initialDLBWPstartSymbolAndLength_2 = 95; + initialDLBWPstartSymbolAndLength_2 = 54; initialDLBWPk0_3 = 0; initialDLBWPmappingType_3 = 0; - #this is SS=2,L=7 - initialDLBWPstartSymbolAndLength_3 = 86; - - initialDLBWPk0_4 = 0; - initialDLBWPmappingType_4 = 0; - #this is SS=2,L=5 - initialDLBWPstartSymbolAndLength_4 = 58; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; #uplinkConfigCommon #frequencyInfoUL From b4bf06f7912788d2498fa9f496720872aefbd86c Mon Sep 17 00:00:00 2001 From: rmagueta Date: Fri, 7 May 2021 20:13:17 +0100 Subject: [PATCH 089/185] CCE-to-REG mapping extended for 2 or more DCI symbols --- openair1/PHY/NR_TRANSPORT/nr_dci.c | 100 ++++++++++++----------- openair1/PHY/NR_TRANSPORT/nr_dci_tools.c | 10 +-- 2 files changed, 56 insertions(+), 54 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 9d3ee61ad1..6c583b64ef 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -182,62 +182,64 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, } /*Mapping the encoded DCI along with the DMRS */ - for (int cce_count = 0; cce_count < dci_pdu->AggregationLevel; cce_count ++) { + for(int symbol = 0; symbol < pdcch_pdu_rel15->DurationSymbols; symbol++) { + for (int cce_count = 0; cce_count < dci_pdu->AggregationLevel; cce_count+=pdcch_pdu_rel15->DurationSymbols) { - int8_t cce_idx = reg_list_order[cce_count]; + int8_t cce_idx = reg_list_order[cce_count]; - for (int reg_in_cce_idx = 0; reg_in_cce_idx < NR_NB_REG_PER_CCE; reg_in_cce_idx++) { + for (int reg_in_cce_idx = 0; reg_in_cce_idx < NR_NB_REG_PER_CCE; reg_in_cce_idx++) { - k = cset_start_sc + gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].start_sc_idx; - - if (k >= frame_parms.ofdm_symbol_size) - k -= frame_parms.ofdm_symbol_size; - - l = cset_start_symb + gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].symb_idx; - - // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 - if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - dmrs_idx =(gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx / pdcch_pdu_rel15->DurationSymbols) * 3; - else - dmrs_idx = (gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx / pdcch_pdu_rel15->DurationSymbols + rb_offset) * 3; - - k_prime = 0; - - for (int m = 0; m < NR_NB_SC_PER_RB; m++) { - if (m == (k_prime << 2) + 1) { // DMRS if not already mapped - ((int16_t *) txdataF)[(l * frame_parms.ofdm_symbol_size + k) << 1] = - (amp * mod_dmrs[l][dmrs_idx << 1]) >> 15; - ((int16_t *) txdataF)[((l * frame_parms.ofdm_symbol_size + k) << 1) + 1] = - (amp * mod_dmrs[l][(dmrs_idx << 1) + 1]) >> 15; - -#ifdef DEBUG_PDCCH_DMRS - printf("PDCCH DMRS: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], - ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); -#endif - - dmrs_idx++; - k_prime++; - - } else { // DCI payload - ((int16_t *) txdataF)[(l * frame_parms.ofdm_symbol_size + k) << 1] = (amp * mod_dci[dci_idx << 1]) >> 15; - ((int16_t *) txdataF)[((l * frame_parms.ofdm_symbol_size + k) << 1) + 1] = - (amp * mod_dci[(dci_idx << 1) + 1]) >> 15; -#ifdef DEBUG_DCI - printf("PDCCH: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], - ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); -#endif - - dci_idx++; - } - - k++; + k = cset_start_sc + gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].start_sc_idx; if (k >= frame_parms.ofdm_symbol_size) k -= frame_parms.ofdm_symbol_size; - } // m - } // reg_in_cce_idx - } // cce_count + l = cset_start_symb + symbol; + + // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 + if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) + dmrs_idx = (gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx) * 3; + else + dmrs_idx = (gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx + rb_offset) * 3; + + k_prime = 0; + + for (int m = 0; m < NR_NB_SC_PER_RB; m++) { + if (m == (k_prime << 2) + 1) { // DMRS if not already mapped + ((int16_t *) txdataF)[(l * frame_parms.ofdm_symbol_size + k) << 1] = + (amp * mod_dmrs[l][dmrs_idx << 1]) >> 15; + ((int16_t *) txdataF)[((l * frame_parms.ofdm_symbol_size + k) << 1) + 1] = + (amp * mod_dmrs[l][(dmrs_idx << 1) + 1]) >> 15; + +#ifdef DEBUG_PDCCH_DMRS + printf("PDCCH DMRS: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); +#endif + + dmrs_idx++; + k_prime++; + + } else { // DCI payload + ((int16_t *) txdataF)[(l * frame_parms.ofdm_symbol_size + k) << 1] = (amp * mod_dci[dci_idx << 1]) >> 15; + ((int16_t *) txdataF)[((l * frame_parms.ofdm_symbol_size + k) << 1) + 1] = + (amp * mod_dci[(dci_idx << 1) + 1]) >> 15; +#ifdef DEBUG_DCI + printf("PDCCH: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], + ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); +#endif + + dci_idx++; + } + + k++; + + if (k >= frame_parms.ofdm_symbol_size) + k -= frame_parms.ofdm_symbol_size; + + } // m + } // reg_in_cce_idx + } // cce_count + } // symbol LOG_D(PHY, "DCI: payloadSize = %d | payload = %llx\n", diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index 4775851a65..0d32cf2732 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -136,7 +136,7 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset); - int N_reg = n_rb * pdcch_pdu_rel15->DurationSymbols; + int N_reg = n_rb; int C=-1; AssertFatal(N_reg > 0,"N_reg cannot be 0\n"); @@ -174,8 +174,8 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r for (uint8_t reg_idx=0; reg_idxreg_list[reg_idx]; reg->reg_idx = bsize*idx + reg_idx; - reg->start_sc_idx = (reg->reg_idx/pdcch_pdu_rel15->DurationSymbols) * NR_NB_SC_PER_RB; - reg->symb_idx = reg->reg_idx % pdcch_pdu_rel15->DurationSymbols; + reg->start_sc_idx = reg->reg_idx * NR_NB_SC_PER_RB; + reg->symb_idx = 0; LOG_D(PHY, "reg %d symbol %d start subcarrier %d\n", reg->reg_idx, reg->symb_idx, reg->start_sc_idx); } } @@ -185,8 +185,8 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r for (uint8_t reg_idx=0; reg_idxreg_list[reg_idx]; reg->reg_idx = cce->cce_idx*NR_NB_REG_PER_CCE + reg_idx; - reg->start_sc_idx = (reg->reg_idx/pdcch_pdu_rel15->DurationSymbols) * NR_NB_SC_PER_RB; - reg->symb_idx = reg->reg_idx % pdcch_pdu_rel15->DurationSymbols; + reg->start_sc_idx = reg->reg_idx * NR_NB_SC_PER_RB; + reg->symb_idx = 0; LOG_D(PHY, "reg %d symbol %d start subcarrier %d\n", reg->reg_idx, reg->symb_idx, reg->start_sc_idx); } From 4204b8bb4cd5bd3a2beb6e8dd0258b338ada868e Mon Sep 17 00:00:00 2001 From: rmagueta Date: Mon, 10 May 2021 20:11:26 +0100 Subject: [PATCH 090/185] CCE-to-REG mapping extended for 2 or more DCI symbols at UE --- openair1/PHY/NR_TRANSPORT/nr_dci.c | 6 ++--- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 34 ++++++++++++++++----------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 6c583b64ef..a7721c68df 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -182,7 +182,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, } /*Mapping the encoded DCI along with the DMRS */ - for(int symbol = 0; symbol < pdcch_pdu_rel15->DurationSymbols; symbol++) { + for(int symbol_idx = 0; symbol_idx < pdcch_pdu_rel15->DurationSymbols; symbol_idx++) { for (int cce_count = 0; cce_count < dci_pdu->AggregationLevel; cce_count+=pdcch_pdu_rel15->DurationSymbols) { int8_t cce_idx = reg_list_order[cce_count]; @@ -194,7 +194,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, if (k >= frame_parms.ofdm_symbol_size) k -= frame_parms.ofdm_symbol_size; - l = cset_start_symb + symbol; + l = cset_start_symb + symbol_idx; // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) @@ -239,7 +239,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, } // m } // reg_in_cce_idx } // cce_count - } // symbol + } // symbol_idx LOG_D(PHY, "DCI: payloadSize = %d | payload = %llx\n", diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index dd33544ce5..24be04d665 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -142,7 +142,7 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, if (reg_bundle_size_L != 0) { // interleaving will be done only if reg_bundle_size_L != 0 coreset_interleaved = 1; - coreset_C = (uint32_t) ((coreset_nbr_rb * coreset_time_dur) / (coreset_interleaver_size_R * reg_bundle_size_L)); + coreset_C = (uint32_t) (coreset_nbr_rb / (coreset_interleaver_size_R * reg_bundle_size_L)); } else { reg_bundle_size_L = 6; } @@ -150,7 +150,7 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, int f_bundle_j_list[NR_MAX_PDCCH_AGG_LEVEL] = {}; - for (int reg = 0; reg < ((coreset_nbr_rb * coreset_time_dur)); reg++) { + for (int reg = 0; reg < coreset_nbr_rb; reg++) { if ((reg % reg_bundle_size_L) == 0) { if (r == coreset_interleaver_size_R) { r = 0; @@ -158,7 +158,7 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, } bundle_j = (c * coreset_interleaver_size_R) + r; - f_bundle_j = ((r * coreset_C) + c + n_shift) % ((coreset_nbr_rb * coreset_time_dur) / reg_bundle_size_L); + f_bundle_j = ((r * coreset_C) + c + n_shift) % (coreset_nbr_rb / reg_bundle_size_L); if (coreset_interleaved == 0) f_bundle_j = bundle_j; @@ -184,22 +184,28 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, } } - for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) { + int rb = 0; + for (int c_id = 0; c_id < number_of_candidates; c_id++ ) { + for (int symbol_idx = 0; symbol_idx < coreset_time_dur; symbol_idx++) { + for (int cce_count = CCE[c_id/coreset_time_dur]+c_id%coreset_time_dur; cce_count < CCE[c_id/coreset_time_dur]+c_id%coreset_time_dur+L[c_id]; cce_count += coreset_time_dur) { + for (int reg_in_cce_idx = 0; reg_in_cce_idx < NR_NB_REG_PER_CCE; reg_in_cce_idx++) { - f_reg = (f_bundle_j_list_ord[reg/6]*reg_bundle_size_L)+(reg%reg_bundle_size_L); - index_z = 9*reg; - index_llr = 9*((uint16_t)floor(f_reg/coreset_time_dur)+((f_reg%coreset_time_dur)*(coreset_nbr_rb))); + f_reg = (f_bundle_j_list_ord[cce_count] * reg_bundle_size_L) + reg_in_cce_idx; + index_z = 9 * rb; + index_llr = (uint16_t) (f_reg + symbol_idx * coreset_nbr_rb) * 9; - for (int i=0; i<9; i++) { - z[index_z + i] = llr[index_llr + i]; + for (int i = 0; i < 9; i++) { + z[index_z + i] = llr[index_llr + i]; #ifdef NR_PDCCH_DCI_DEBUG - LOG_D(PHY,"[reg=%d,bundle_j=%d] z[%d]=(%d,%d) <-> \t[f_reg=%d,fbundle_j=%d] llr[%d]=(%d,%d) \n", - reg,bundle_j,(index_z + i),*(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i]), - f_reg,f_bundle_j,(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i])); + LOG_I(PHY,"[cce_count=%d,reg_in_cce_idx=%d,bundle_j=%d,symbol_idx=%d,candidate=%d] z[%d]=(%d,%d) <-> \t[f_reg=%d,fbundle_j=%d] llr[%d]=(%d,%d) \n", + cce_count,reg_in_cce_idx,bundle_j,symbol_idx,c_id,(index_z + i),*(int16_t *) &z[index_z + i],*(1 + (int16_t *) &z[index_z + i]), + f_reg,f_bundle_j,(index_llr + i),*(int16_t *) &llr[index_llr + i], *(1 + (int16_t *) &llr[index_llr + i])); #endif + } + rb++; + } + } } - - if ((reg%reg_bundle_size_L) == 0) r++; } } From c02d9f622199ce218a9b123e610172aa87942577 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 18 May 2021 15:01:41 +0200 Subject: [PATCH 091/185] improvements in configure_pdcch function --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 16 ++--------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 10 +++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 9 ++++--- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 27 +++++++++++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 6 ++--- 6 files changed, 30 insertions(+), 40 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 00045074f4..c3caa04d28 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -973,17 +973,10 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(nr_mac,pdcch_pdu_rel15, ss, coreset, scc, bwp); + nr_configure_pdcch(pdcch_pdu_rel15, ss, coreset, scc, genericParameters, NULL); nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu_rel15; } - // TODO: This assignment should be done in function nr_configure_pdcch() - if(get_softmodem_params()->sa) { - pdcch_pdu_rel15->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG_CSET_0; - pdcch_pdu_rel15->BWPSize = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - pdcch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - } - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; @@ -1330,15 +1323,10 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(nr_mac, pdcch_pdu_rel15, ss, coreset, scc, bwp); + nr_configure_pdcch(pdcch_pdu_rel15, ss, coreset, scc, genericParameters, NULL); nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu_rel15; } - // TODO: This assignment should be done in function nr_configure_pdcch() - pdcch_pdu_rel15->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG_CSET_0; - pdcch_pdu_rel15->BWPSize = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - pdcch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 2c567fa871..fd094bc8db 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -423,16 +423,12 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(gNB_mac, - pdcch_pdu_rel15, + nr_configure_pdcch(pdcch_pdu_rel15, gNB_mac->sched_ctrlCommon->search_space, gNB_mac->sched_ctrlCommon->coreset, scc, - NULL); - - pdcch_pdu_rel15->BWPSize = type0_PDCCH_CSS_config->num_rbs; - pdcch_pdu_rel15->BWPStart = type0_PDCCH_CSS_config->cset_start_rb; - pdcch_pdu_rel15->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch; + NULL, + type0_PDCCH_CSS_config); nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index e5e097aa24..ad84737003 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -806,6 +806,10 @@ void nr_schedule_ue_spec(module_id_t module_id, /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not * exist, create it */ + + // BWP + NR_BWP_t *genericParameters = bwp ? &bwp->bwp_Common->genericParameters : &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; + const int bwpid = bwp ? bwp->bwp_Id : 0; const int coresetid = bwp ? sched_ctrl->coreset->controlResourceSetId : gNB_mac->sched_ctrlCommon->coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; @@ -819,7 +823,7 @@ void nr_schedule_ue_spec(module_id_t module_id, LOG_I(NR_MAC,"Trying to configure DL pdcch for bwp %d, cs %d\n",bwpid,coresetid); NR_SearchSpace_t *ss = bwp ? sched_ctrl->search_space:gNB_mac->sched_ctrlCommon->search_space; NR_ControlResourceSet_t *coreset = bwp? sched_ctrl->coreset:gNB_mac->sched_ctrlCommon->coreset; - nr_configure_pdcch(gNB_mac, pdcch_pdu, ss, coreset, scc, bwp); + nr_configure_pdcch(pdcch_pdu, ss, coreset, scc, genericParameters, NULL); gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu; } @@ -838,9 +842,6 @@ void nr_schedule_ue_spec(module_id_t module_id, const int pduindex = gNB_mac->pdu_index[CC_id]++; pdsch_pdu->pduIndex = pduindex; - // BWP - NR_BWP_t *genericParameters = bwp ? &bwp->bwp_Common->genericParameters : &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; - pdsch_pdu->BWPSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); pdsch_pdu->BWPStart = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth,MAX_BWP_SIZE); pdsch_pdu->SubcarrierSpacing = genericParameters->subcarrierSpacing; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index bbe0f62f9c..de520f64be 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -586,25 +586,27 @@ int nr_get_default_pucch_res(int pucch_ResourceCommon) { return(default_pucch_csset[pucch_ResourceCommon]); } -void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, +void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, NR_ServingCellConfigCommon_t *scc, - NR_BWP_Downlink_t *bwp) -{ + NR_BWP_t *bwp, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) { int sps; if (bwp) { // This is not for SIB1 - pdcch_pdu->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - pdcch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - pdcch_pdu->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; - pdcch_pdu->CyclicPrefix = (bwp->bwp_Common->genericParameters.cyclicPrefix==NULL) ? 0 : *bwp->bwp_Common->genericParameters.cyclicPrefix; + pdcch_pdu->BWPSize = NRRIV2BW(bwp->locationAndBandwidth, MAX_BWP_SIZE); + pdcch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->locationAndBandwidth, MAX_BWP_SIZE); + pdcch_pdu->SubcarrierSpacing = bwp->subcarrierSpacing; + pdcch_pdu->CyclicPrefix = (bwp->cyclicPrefix==NULL) ? 0 : *bwp->cyclicPrefix; //AssertFatal(pdcch_scs==kHz15, "PDCCH SCS above 15kHz not allowed if a symbol above 2 is monitored"); - sps = bwp->bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; + sps = bwp->cyclicPrefix == NULL ? 14 : 12; } else { + pdcch_pdu->BWPSize = type0_PDCCH_CSS_config->num_rbs; + pdcch_pdu->BWPStart = type0_PDCCH_CSS_config->cset_start_rb; + pdcch_pdu->SubcarrierSpacing = type0_PDCCH_CSS_config->scs_pdcch; pdcch_pdu->CyclicPrefix = 0; sps = 14; } @@ -635,7 +637,7 @@ void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, if (pdcch_pdu->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { pdcch_pdu->RegBundleSize = (coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->reg_BundleSize); - pdcch_pdu->InterleaverSize = (coreset->cce_REG_MappingType.choice.interleaved->interleaverSize==NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->interleaverSize); + pdcch_pdu->InterleaverSize = (coreset->cce_REG_MappingType.choice.interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2+coreset->cce_REG_MappingType.choice.interleaved->interleaverSize); AssertFatal(scc->physCellId != NULL,"scc->physCellId is null\n"); pdcch_pdu->ShiftIndex = coreset->cce_REG_MappingType.choice.interleaved->shiftIndex != NULL ? *coreset->cce_REG_MappingType.choice.interleaved->shiftIndex : *scc->physCellId; } @@ -646,7 +648,10 @@ void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, } if(coreset->controlResourceSetId == 0) { - pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; + if(bwp == NULL) + pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; + else + pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG_CSET_0; } else{ pdcch_pdu->CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index cbb428bbf7..fb140dcaac 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1235,7 +1235,7 @@ void nr_schedule_ulsch(module_id_t module_id, ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; ul_dci_req->numPdus += 1; - nr_configure_pdcch(RC.nrmac[module_id], pdcch_pdu, ss, coreset, scc, sched_ctrl->active_bwp); + nr_configure_pdcch(pdcch_pdu, ss, coreset, scc, genericParameters, NULL); pdcch_pdu_bwp_coreset[bwpid][coresetid] = pdcch_pdu; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 144cca09d1..edc553c92b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -244,12 +244,12 @@ void find_search_space(int ss_type, NR_BWP_Downlink_t *bwp, NR_SearchSpace_t *ss); -void nr_configure_pdcch(gNB_MAC_INST *gNB_mac, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, +void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, NR_ServingCellConfigCommon_t *scc, - NR_BWP_Downlink_t *bwp); + NR_BWP_t *bwp, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config); void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, const NR_CellGroupConfig_t *CellGroup, From de7d35007c6046edaeb56dbf9d18cfb70d6a7513 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sat, 22 May 2021 16:26:00 +0200 Subject: [PATCH 092/185] temporary revert to 1 estimate per PRB for performance evaluation --- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 1 - .../NR_ESTIMATION/nr_ul_channel_estimation.c | 25 +++++++++++++++++-- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 7 +++--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index ca5108ef45..96163b22e8 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -55,7 +55,6 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) int Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; temp += (Re*Re/2) + (Im*Im/2); } - if (temp > max_val) { max_pos = i; max_val = temp; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 1ba55f3df3..fe683ca0bc 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -37,6 +37,7 @@ //#define DEBUG_CH //#define DEBUG_PUSCH +#define NO_INTERP 1 #define dBc(x,y) (dB_fixed(((int32_t)(x))*(x) + ((int32_t)(y))*(y))) int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, @@ -187,7 +188,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, //if ((gNB->frame_parms.N_RB_UL&1)==0) { if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && gNB->fd_interpolation == 1){ - + LOG_D(PHY,"PUSCH estimation DMRS type 1, Freq-domain interpolation"); // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); @@ -432,7 +433,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #endif } else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && gNB->fd_interpolation == 1) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| - + LOG_D(PHY,"PUSCH estimation DMRS type 2, Freq-domain interpolation"); // Treat first DMRS specially (left edge) rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; @@ -518,6 +519,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + LOG_D(PHY,"PUSCH estimation DMRS type 1, no Freq-domain interpolation"); int32_t ch_0, ch_1; // First PRB ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; @@ -565,6 +567,13 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; + + + +#ifdef NO_INTERP + for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; + ul_ch+=24; +#else multadd_real_vector_complex_scalar(filt8_avlip0, ch, ul_ch, @@ -582,6 +591,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch, 8); ul_ch -= 24; +#endif for (pilot_cnt=6; pilot_cnt<6*(nb_rb_pusch-1); pilot_cnt += 6) { @@ -630,6 +640,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; +#ifdef NO_INTERP + for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; + ul_ch+=24; +#else ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 @@ -651,6 +665,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ul_ch, 8); ul_ch -= 16; +#endif } // Last PRB ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; @@ -698,6 +713,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; +#ifdef NO_INTERP + for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; + ul_ch+=24; +#else ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 @@ -712,8 +731,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch, ul_ch, 8); +#endif } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + LOG_D(PHY,"PUSCH estimation DMRS type 2, no Freq-domain interpolation"); int32_t ch_0, ch_1; //First PRB ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 9023966427..8dd06d476b 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -371,12 +371,13 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; + int sync_pos_rounded; // do some integer rounding to improve TA accuracy if (sync_pos > 0) - sync_pos += bw_scaling / 2 - 1; + sync_pos_rounded = sync_pos + (bw_scaling / 2) - 1; else if(sync_pos < 0) - sync_pos -= bw_scaling / 2 - 1; - timing_advance_update = sync_pos / bw_scaling; + sync_pos_rounded = sync_pos - (bw_scaling / 2) - 1; + timing_advance_update = sync_pos_rounded / bw_scaling; // put timing advance command in 0..63 range timing_advance_update += 31; From 0c84d4db02c809f03a595b0b37ad3eca8622981a Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sun, 23 May 2021 16:57:49 +0200 Subject: [PATCH 093/185] printing time response in ulsim --- openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 6 +++--- openair1/SIMULATION/NR_PHY/ulsim.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index fe683ca0bc..e6eed513b0 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -570,7 +570,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, -#ifdef NO_INTERP +#if NO_INTERP for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; ul_ch+=24; #else @@ -640,7 +640,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; -#ifdef NO_INTERP +#if NO_INTERP for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; ul_ch+=24; #else @@ -713,7 +713,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; -#ifdef NO_INTERP +#if NO_INTERP for (int i=0;i<12;i++) ((int32_t*)ul_ch)[i] = *(int32_t*)ch; ul_ch+=24; #else diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 4e00b53b18..9b07386ca0 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1228,6 +1228,8 @@ int main(int argc, char **argv) &gNB->pusch_vars[0]->rxdataF_ext[0][start_symbol*NR_NB_SC_PER_RB * pusch_pdu->rb_size],nb_symb_sch*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); LOG_M("chestF0.m","chF0", &gNB->pusch_vars[0]->ul_ch_estimates[0][start_symbol*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); + LOG_M("chestT0.m","chT0", + &gNB->pusch_vars[0]->ul_ch_estimates_time[0][0],frame_parms->ofdm_symbol_size,1,1); LOG_M("chestF0_ext.m","chF0_ext", &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(start_symbol+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], (nb_symb_sch-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); From cf0659abe9c384158c4bb046795c1bc7fa1922a7 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Mon, 31 May 2021 02:13:19 +0530 Subject: [PATCH 094/185] Cleanup --- ci-scripts/ran.py | 1 - ci-scripts/runTestOnVM.sh | 27 +- ci-scripts/xml_files/benetel_nsa_base.xml | 162 - ci-scripts/xml_files/fr1_nsa_base_ref.xml | 161 - executables/nr-gnb.c | 33 +- executables/nr-ru.c | 38 +- executables/nr-ru_Original.c | 2514 --- nfapi/oai_integration/nfapi_pnf.c | 40 +- nfapi/oai_integration/nfapi_pnf.h | 1 - nfapi/oai_integration/nfapi_vnf.c | 2 +- nfapi/open-nFAPI/common/src/debug.c | 152 +- .../nfapi/public_inc/fapi_nr_ue_interface.h | 8 +- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 9 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 17074 ++++++++-------- .../pnf/public_inc/nfapi_pnf_interface.h | 1 + nfapi/open-nFAPI/pnf/src/pnf_p7.c | 27 +- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 72 +- nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp | 4 +- nfapi/open-nFAPI/vnf/inc/vnf_p7.h | 2 + nfapi/open-nFAPI/vnf/src/vnf_p7.c | 764 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 12 - .../NR_ESTIMATION/nr_ul_channel_estimation.c | 2 + openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c | 22 +- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 13 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 11 +- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 4 +- .../nr_dlsch_llr_computation.c | 52 +- .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 14 +- openair1/SCHED_NR/fapi_nr_l1.c | 16 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 6 +- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 2 +- openair1/SCHED_NR_UE/harq_nr.c | 2 +- openair1/SIMULATION/NR_PHY/dlsim.c | 15 - openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 5 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 20 - .../NR_MAC_gNB/gNB_scheduler_primitives.c | 8 - .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 149 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 37 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 4 +- 39 files changed, 9565 insertions(+), 11921 deletions(-) delete mode 100644 ci-scripts/xml_files/benetel_nsa_base.xml delete mode 100644 ci-scripts/xml_files/fr1_nsa_base_ref.xml delete mode 100644 executables/nr-ru_Original.c diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 31027d7234..83945b3c17 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -246,7 +246,6 @@ class RANManagement(): while (count > 0) and buildOAIprocess: mySSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 6) result = re.search('build_oai', mySSH.getBefore()) - print(result) if result is None: buildOAIprocess = False else: diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 7bd261fa0a..fc35370e0a 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -2204,43 +2204,26 @@ function run_test_on_vm { mkdir --parents $ARCHIVES_LOC fi - CN_CONFIG="noS1" - S1_NOS1_CFG=0 + local try_cnt=0 + NR_STATUS=0 ######### start of RA TEST loop - # for the moment only TDD - TRANS_MODES=("tdd") - for TMODE in ${TRANS_MODES[@]} + while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI do - if [[ $TMODE =~ .*fdd.* ]] - then - CONF_FILE=gnb.band66.tm1.106PRB.usrpn300.conf - PRB=106 - FREQUENCY=37000 - else - CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf - PRB=106 - FREQUENCY=3510 - fi - local try_cnt=0 - NR_STATUS=0 - while [ $try_cnt -lt 5 ] #5 because it hardly succeed within CI - - do SYNC_STATUS=0 RA_FR2_STATUS=0 rm -f $ARCHIVES_LOC/tdd_${PRB}prb_${CN_CONFIG}*ra_fr2_test.log echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB in ${TMODE} mode (RA TEST)" + echo "${CN_CONFIG} : Starting the gNB" echo "############################################################" CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb_ra_fr2_test.log #last argument = 1 is to enable --do-ra for RA test start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1 echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE in ${TMODE} mode (RA TEST)" + echo "${CN_CONFIG} : Starting the NR-UE" echo "############################################################" CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue_ra_fr2_test.log #last argument = 1 is to enable --do-ra for RA test diff --git a/ci-scripts/xml_files/benetel_nsa_base.xml b/ci-scripts/xml_files/benetel_nsa_base.xml deleted file mode 100644 index 0aed28dffa..0000000000 --- a/ci-scripts/xml_files/benetel_nsa_base.xml +++ /dev/null @@ -1,162 +0,0 @@ - - - TEST-FR1-TM1 - FR1 - tasks - - 010000 - 030000 - 040000 - 010001 - 000001 - 050000 - 050001 - 000001 - 060000 - 060001 - 000001 - 070000 - 070001 - 010002 - 000001 - 080001 - 080000 - 010003 - - - - - Initialize_UE - Initialize UE - - - - Terminate_UE - Terminate UE - - - - Attach_UE - Attach UE - - - - Detach_UE - Detach UE - - - - - Initialize_eNB - Initialize eNB - -O ci-scripts/conf_files/benetel-4g.conf - 0 - 0 - lte - - - - - Initialize_eNB - Initialize gNB - -O ci-scripts/conf_files/benetel-5g.conf - 1 - 1 - nr - - - - IdleSleep - Sleep - 20 - - - - Ping - Ping: 20pings in 20sec - -c 20 - 50 - - - - Ping - Ping: 100pings in 20sec - -c 100 -i 0.2 - 50 - - - - - Iperf - iperf (DL/2.5Mbps/UDP)(60 sec)(single-ue profile) - -u -b 2.5M -t 60 -i 1 - 50 - single-ue - - - - Iperf - iperf (UL/1.5Mbps/UDP)(60 sec)(single-ue profile) - -u -b 1.5M -t 60 -i 1 -R - 50 - single-ue - - - - - Iperf - iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) - -u -b 20M -t 20 -i 1 - 50 - single-ue - - - - Iperf - iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) - -u -b 3M -t 20 -i 1 -R - 50 - single-ue - - - - - - Terminate_eNB - Terminate eNB - 0 - 0 - lte - - - - Terminate_eNB - Terminate gNB - 1 - 1 - nr - - - - diff --git a/ci-scripts/xml_files/fr1_nsa_base_ref.xml b/ci-scripts/xml_files/fr1_nsa_base_ref.xml deleted file mode 100644 index fd47db10b2..0000000000 --- a/ci-scripts/xml_files/fr1_nsa_base_ref.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - TEST-NSA-FR1-TM1 - NSA FULL - tasks - - 010000 - 030000 - 040000 - 010001 - 000001 - 050000 - 050001 - 000001 - 060000 - 060001 - 000001 - 070000 - 010002 - 000001 - 080001 - 080000 - 010003 - - - - - Initialize_UE - Initialize UE - - - - Terminate_UE - Terminate UE - - - - Attach_UE - Attach UE - - - - Detach_UE - Detach UE - - - - - Initialize_eNB - Initialize eNB - -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf - 0 - 0 - lte - - - - - Initialize_eNB - Initialize gNB - -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E - 1 - 1 - nr - - - - IdleSleep - Sleep - 20 - - - - Ping - Ping: 20pings in 20sec - -c 20 - 50 - - - - Ping - Ping: 100pings in 20sec - -c 100 -i 0.2 - 50 - - - - - Iperf - iperf (DL/3Mbps/UDP)(20 sec)(single-ue profile) - -u -b 3M -t 20 -i 1 - 50 - single-ue - - - - Iperf - iperf (UL/1Mbps/UDP)(20 sec)(single-ue profile) - -u -b 1M -t 20 -i 1 -R - 50 - single-ue - - - - - Iperf - iperf (DL/20Mbps/UDP)(20 sec)(single-ue profile) - -u -b 20M -t 20 -i 1 - 50 - single-ue - - - - Iperf - iperf (UL/3Mbps/UDP)(20 sec)(single-ue profile) - -u -b 3M -t 20 -i 1 -R - 50 - single-ue - - - - - - Terminate_eNB - Terminate eNB - 0 - 0 - lte - - - - Terminate_eNB - Terminate gNB - 1 - 1 - nr - - - - diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 5e46f0b6f8..576c10229c 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -229,34 +229,9 @@ void rx_func(void *param) { if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); // RX processing - int tx_slot_type; int rx_slot_type; - if(NFAPI_MODE != NFAPI_MONOLITHIC) { //slot selection routines not working properly in nfapi, so temporarily hardcoding - if ((slot_tx==8) || (slot_tx==9) || (slot_tx==18) || (slot_tx==19)) { //tx slot config - tx_slot_type = NR_UPLINK_SLOT; - } - else if ((slot_tx==7) || (slot_tx==17)) { - tx_slot_type = NR_MIXED_SLOT; - } - else { - tx_slot_type = NR_DOWNLINK_SLOT;; - } + int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); + int rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); - if ((slot_rx==8) || (slot_rx==9) || (slot_rx==18) || (slot_rx==19)) { // rx slot config - rx_slot_type = NR_UPLINK_SLOT; - } - else if ((slot_rx==7) || (slot_rx==17)) { - rx_slot_type = NR_MIXED_SLOT; - } - else { - rx_slot_type = NR_DOWNLINK_SLOT;; - } - - - } - else { - tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx); - rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); - } if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { // UE-specific RX processing for subframe n // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT @@ -281,7 +256,8 @@ void rx_func(void *param) { // Call the scheduler - start_meas(&gNB->ul_indication_stats); + if (NFAPI_MODE == NFAPI_MONOLITHIC){ + start_meas(&gNB->ul_indication_stats); pthread_mutex_lock(&gNB->UL_INFO_mutex); gNB->UL_INFO.frame = frame_rx; gNB->UL_INFO.slot = slot_rx; @@ -290,6 +266,7 @@ void rx_func(void *param) { gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); stop_meas(&gNB->ul_indication_stats); + } notifiedFIFO_elt_t *res; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 5eff0f35b8..360bd97287 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -97,8 +97,6 @@ static int DEFBFW[] = {0x00007fff}; extern volatile int oai_exit; -extern struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); -extern struct timespec timespec_add(struct timespec lhs, struct timespec rhs); extern void nr_phy_free_RU(RU_t *); extern void nr_phy_config_request(NR_PHY_Config_t *gNB); #include "executables/thread-common.h" @@ -710,8 +708,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { - +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -1302,35 +1299,10 @@ void *ru_thread( void *param ) { } // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices - struct timespec slot_start; - clock_gettime(CLOCK_MONOTONIC, &slot_start); - struct timespec slot_duration; - slot_duration.tv_sec = 0; - //slot_duration.tv_nsec = 0.5e6; - slot_duration.tv_nsec = 0.5e6; - - - while (!oai_exit) { // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. // They are set on the first rx/tx in the underly FH routines. - slot_start = timespec_add(slot_start,slot_duration); - struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); - - struct timespec sleep_time; - - if((slot_start.tv_sec > curr_time.tv_sec) || (slot_start.tv_sec == curr_time.tv_sec && slot_start.tv_nsec > curr_time.tv_nsec)){ - sleep_time = timespec_sub(slot_start,curr_time); - - usleep(sleep_time.tv_nsec * 1e-3); - } - else{//continue - } - - // clock_gettime(CLOCK_MONOTONIC, &curr_time); - //printf("sfn:%d, slot:%d, start time %d.%d slot start %d.%d \n",frame,slot,curr_time.tv_sec,curr_time.tv_nsec,slot_start.tv_sec,slot_start.tv_nsec); if (slot==(fp->slots_per_frame-1)) { slot=0; frame++; @@ -1359,13 +1331,7 @@ void *ru_thread( void *param ) { // do RX front-end processing (frequency-shift, dft) if needed - //int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); - //if (NFAPI_MODE == NFAPI_MODE_PNF) - int slot_type; - if (slot ==7) - slot_type = NR_MIXED_SLOT; - if (slot == 8) - slot_type = NR_UPLINK_SLOT; + int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { if (ru->feprx) { diff --git a/executables/nr-ru_Original.c b/executables/nr-ru_Original.c deleted file mode 100644 index 73421d8ed7..0000000000 --- a/executables/nr-ru_Original.c +++ /dev/null @@ -1,2514 +0,0 @@ -/* - * 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 - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all - -#include "common/utils/assertions.h" -#include "common/utils/system.h" -#include "msc.h" - -#include "../../ARCH/COMMON/common_lib.h" -#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h" - -#include "PHY/LTE_TRANSPORT/if4_tools.h" -#include "PHY/LTE_TRANSPORT/if5_tools.h" - -#include "PHY/types.h" -#include "PHY/defs_nr_common.h" -#include "PHY/phy_extern.h" -#include "PHY/LTE_TRANSPORT/transport_proto.h" -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" -#include "PHY/INIT/phy_init.h" -#include "SCHED/sched_eNB.h" -#include "SCHED_NR/sched_nr.h" - -#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -#include "RRC/LTE/rrc_extern.h" -#include "PHY_INTERFACE/phy_interface.h" - -#include "common/utils/LOG/log.h" -#include "common/utils/LOG/vcd_signal_dumper.h" - -#include "enb_config.h" -#include - -#ifdef SMBV -#include "PHY/TOOLS/smbv.h" -unsigned short config_frames[4] = {2,9,11,13}; -#endif - -/* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */ -static int DEFBANDS[] = {7}; -static int DEFENBS[] = {0}; -static int DEFBFW[] = {0x00007fff}; - -//static int DEFNRBANDS[] = {7}; -//static int DEFGNBS[] = {0}; - -#include "ENB_APP/enb_paramdef.h" -#include "GNB_APP/gnb_paramdef.h" -#include "common/config/config_userapi.h" - -#ifndef OPENAIR2 - #include "UTIL/OTG/otg_extern.h" -#endif - -#include "s1ap_eNB.h" -#include "SIMULATION/ETH_TRANSPORT/proto.h" - - - -#include "T.h" -#include "nfapi_interface.h" - -extern volatile int oai_exit; - - -extern void nr_phy_free_RU(RU_t *); -extern void nr_phy_config_request(NR_PHY_Config_t *gNB); -#include "executables/thread-common.h" -//extern PARALLEL_CONF_t get_thread_parallel_conf(void); -//extern WORKER_CONF_t get_thread_worker_conf(void); - -void init_NR_RU(char *); -void stop_RU(int nb_ru); -void do_ru_sync(RU_t *ru); - -void configure_ru(int idx, void *arg); -void configure_rru(int idx, void *arg); -int attach_rru(RU_t *ru); -int connect_rau(RU_t *ru); - -uint16_t sf_ahead; -uint16_t slot_ahead; -uint16_t sl_ahead; - -extern int emulate_rf; -extern int numerology; -extern int usrp_tx_thread; - -/*************************************************************/ -/* Functions to attach and configure RRU */ - -extern void wait_gNBs(void); - -int attach_rru(RU_t *ru) -{ - ssize_t msg_len,len; - RRU_CONFIG_msg_t rru_config_msg; - int received_capabilities=0; - wait_gNBs(); - - // Wait for capabilities - while (received_capabilities==0) { - memset((void *)&rru_config_msg,0,sizeof(rru_config_msg)); - rru_config_msg.type = RAU_tick; - rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE; - LOG_I(PHY,"Sending RAU tick to RRU %d\n",ru->idx); - AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), - "RU %d cannot access remote radio\n",ru->idx); - msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); - - // wait for answer with timeout - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - msg_len))<0) { - LOG_I(PHY,"Waiting for RRU %d\n",ru->idx); - } else if (rru_config_msg.type == RRU_capabilities) { - AssertFatal(rru_config_msg.len==msg_len,"Received capabilities with incorrect length (%d!=%d)\n",(int)rru_config_msg.len,(int)msg_len); - LOG_I(PHY,"Received capabilities from RRU %d (len %d/%d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n",ru->idx, - (int)rru_config_msg.len,(int)msg_len, - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->num_bands, - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_pdschReferenceSignalPower[0], - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->max_rxgain[0], - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_tx[0], - ((RRU_capabilities_t *)&rru_config_msg.msg[0])->nb_rx[0]); - received_capabilities=1; - } else { - LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); - } - } - - configure_ru(ru->idx, - (RRU_capabilities_t *)&rru_config_msg.msg[0]); - rru_config_msg.type = RRU_config; - rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); - LOG_I(PHY,"Sending Configuration to RRU %d (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n",ru->idx, - ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands, - ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); - AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), - "RU %d failed send configuration to remote radio\n",ru->idx); - - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - msg_len))<0) { - LOG_I(PHY,"Waiting for RRU %d\n",ru->idx); - } else if (rru_config_msg.type == RRU_config_ok) { - LOG_I(PHY, "RRU_config_ok received\n"); - } else { - LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx); - } - - return 0; -} - -int connect_rau(RU_t *ru) -{ - RRU_CONFIG_msg_t rru_config_msg; - ssize_t msg_len; - int tick_received = 0; - int configuration_received = 0; - RRU_capabilities_t *cap; - int i; - int len; - - // wait for RAU_tick - while (tick_received == 0) { - msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE; - - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - msg_len))<0) { - LOG_I(PHY,"Waiting for RAU\n"); - } else { - if (rru_config_msg.type == RAU_tick) { - LOG_I(PHY,"Tick received from RAU\n"); - tick_received = 1; - } else LOG_E(PHY,"Received erroneous message (%d)from RAU, expected RAU_tick\n",rru_config_msg.type); - } - } - - // send capabilities - rru_config_msg.type = RRU_capabilities; - rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_capabilities_t); - cap = (RRU_capabilities_t *)&rru_config_msg.msg[0]; - LOG_I(PHY,"Sending Capabilities (len %d, num_bands %d,max_pdschReferenceSignalPower %d, max_rxgain %d, nb_tx %d, nb_rx %d)\n", - (int)rru_config_msg.len,ru->num_bands,ru->max_pdschReferenceSignalPower,ru->max_rxgain,ru->nb_tx,ru->nb_rx); - - switch (ru->function) { - case NGFI_RRU_IF4p5: - cap->FH_fmt = OAI_IF4p5_only; - break; - - case NGFI_RRU_IF5: - cap->FH_fmt = OAI_IF5_only; - break; - - case MBP_RRU_IF5: - cap->FH_fmt = MBP_IF5; - break; - - default: - AssertFatal(1==0,"RU_function is unknown %d\n",RC.ru[0]->function); - break; - } - - cap->num_bands = ru->num_bands; - - for (i=0; inum_bands; i++) { - LOG_I(PHY,"Band %d: nb_rx %d nb_tx %d pdschReferenceSignalPower %d rxgain %d\n", - ru->band[i],ru->nb_rx,ru->nb_tx,ru->max_pdschReferenceSignalPower,ru->max_rxgain); - cap->band_list[i] = ru->band[i]; - cap->nb_rx[i] = ru->nb_rx; - cap->nb_tx[i] = ru->nb_tx; - cap->max_pdschReferenceSignalPower[i] = ru->max_pdschReferenceSignalPower; - cap->max_rxgain[i] = ru->max_rxgain; - } - - AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1), - "RU %d failed send capabilities to RAU\n",ru->idx); - // wait for configuration - rru_config_msg.len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE+sizeof(RRU_config_t); - - while (configuration_received == 0) { - if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice, - &rru_config_msg, - rru_config_msg.len))<0) { - LOG_I(PHY,"Waiting for configuration from RAU\n"); - } else { - LOG_I(PHY,"Configuration received from RAU (num_bands %d,band0 %d,txfreq %u,rxfreq %u,att_tx %d,att_rx %d,N_RB_DL %d,N_RB_UL %d,3/4FS %d, prach_FO %d, prach_CI %d)\n", - ((RRU_config_t *)&rru_config_msg.msg[0])->num_bands, - ((RRU_config_t *)&rru_config_msg.msg[0])->band_list[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->tx_freq[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->rx_freq[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->att_tx[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->att_rx[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_DL[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->N_RB_UL[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->threequarter_fs[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->prach_FreqOffset[0], - ((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]); - configure_rru(ru->idx, - (void *)&rru_config_msg.msg[0]); - configuration_received = 1; - } - } - - return 0; -} -/*************************************************************/ -/* Southbound Fronthaul functions, RCC/RAU */ - -// southbound IF5 fronthaul for 16-bit OAI format -void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) -{ - if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); - - send_IF5(ru, timestamp, slot, &ru->seqno, IF5_RRH_GW_DL); -} - -// southbound IF4p5 fronthaul -void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) -{ - nfapi_nr_config_request_scf_t *cfg = &ru->config; - if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); - - LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.tti_tx); - - - if ((nr_slot_select(cfg,ru->proc.frame_tx,ru->proc.tti_tx)&NR_DOWNLINK_SLOT) > 0) - send_IF4p5(ru,frame, slot, IF4p5_PDLFFT); -} - -/*************************************************************/ -/* Input Fronthaul from south RCC/RAU */ - -// Synchronous if5 from south -void fh_if5_south_in(RU_t *ru, - int *frame, - int *tti) -{ - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - recv_IF5(ru, &proc->timestamp_rx, *tti, IF5_RRH_GW_UL); - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; - uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe; - proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); - - if (proc->first_rx == 0) { - if (proc->tti_rx != *tti) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*tti); - exit_fun("Exiting"); - } - - if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - *frame = proc->frame_rx; - *tti = proc->tti_rx; - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); -} - -// Synchronous if4p5 from south -void fh_if4p5_south_in(RU_t *ru, - int *frame, - int *slot) -{ - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int f,sl; - uint16_t packet_type; - uint32_t symbol_number=0; - uint32_t symbol_mask_full=0; - - /* - if ((fp->frame_type == TDD) && (subframe_select(fp,*slot)==SF_S)) - symbol_mask_full = (1<ul_symbols_in_S_subframe)-1; - else - symbol_mask_full = (1<symbols_per_slot)-1; - - AssertFatal(proc->symbol_mask[*slot]==0,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*slot,proc->symbol_mask[*slot]);*/ - do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - recv_IF4p5(ru, &f, &sl, &packet_type, &symbol_number); - - if (packet_type == IF4p5_PULFFT) proc->symbol_mask[sl] = proc->symbol_mask[sl] | (1<first_rx==0) && (f!=*frame)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received frame %d != expected %d\n",f,*frame); - - if ((proc->first_rx==0) && (sl!=*slot)) LOG_E(PHY,"rx_fh_if4p5: PULTICK received subframe %d != expected %d (first_rx %d)\n",sl,*slot,proc->first_rx); - - break; - } else if (packet_type == IF4p5_PRACH) { - // nothing in RU for RAU - } - - LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*slot,proc->symbol_mask[sl]); - } while(proc->symbol_mask[sl] != symbol_mask_full); - - //caculate timestamp_rx, timestamp_tx based on frame and subframe - proc->tti_rx = sl; - proc->frame_rx = f; - proc->timestamp_rx = (proc->frame_rx * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(proc->tti_rx, fp, 0); - // proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_subframe); - proc->tti_tx = (sl+(fp->slots_per_subframe*sf_ahead))%fp->slots_per_frame; - proc->frame_tx = (sl>(fp->slots_per_frame-1-(fp->slots_per_subframe*sf_ahead))) ? (f+1)&1023 : f; - - if (proc->first_rx == 0) { - if (proc->tti_rx != *slot) { - LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*slot); - exit_fun("Exiting"); - } - - if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp (IF4p5) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - *frame = proc->frame_rx; - *slot = proc->tti_rx; - } - - if (ru == RC.ru[0]) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, f ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, sl); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, proc->tti_tx ); - } - - proc->symbol_mask[proc->tti_rx] = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - LOG_D(PHY,"RU %d: fh_if4p5_south_in sleeping ...\n",ru->idx); -} - -// asynchronous inbound if4p5 fronthaul from south -void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *slot) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - uint16_t packet_type; - uint32_t symbol_number,symbol_mask,prach_rx; - // uint32_t got_prach_info=0; - symbol_number = 0; - symbol_mask = (1<<(fp->symbols_per_slot))-1; - prach_rx = 0; - - do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! - recv_IF4p5(ru, &proc->frame_rx, &proc->tti_rx, &packet_type, &symbol_number); - - // grab first prach information for this new subframe - /*if (got_prach_info==0) { - prach_rx = is_prach_subframe(fp, proc->frame_rx, proc->tti_rx); - got_prach_info = 1; - }*/ - if (proc->first_rx != 0) { - *frame = proc->frame_rx; - *slot = proc->tti_rx; - proc->first_rx = 0; - } else { - if (proc->frame_rx != *frame) { - LOG_E(PHY,"frame_rx %d is not what we expect %d\n",proc->frame_rx,*frame); - exit_fun("Exiting"); - } - - if (proc->tti_rx != *slot) { - LOG_E(PHY,"tti_rx %d is not what we expect %d\n",proc->tti_rx,*slot); - exit_fun("Exiting"); - } - } - - if (packet_type == IF4p5_PULFFT) symbol_mask &= (~(1< 0) || (prach_rx >0)); // haven't received all PUSCH symbols and PRACH information -} - - - - - -/*************************************************************/ -/* Input Fronthaul from North RRU */ - -// RRU IF4p5 TX fronthaul receiver. Assumes an if_device on input and if or rf device on output -// receives one subframe's worth of IF4p5 OFDM symbols and OFDM modulates -void fh_if4p5_north_in(RU_t *ru,int *frame,int *slot) { - uint32_t symbol_number=0; - uint32_t symbol_mask, symbol_mask_full; - uint16_t packet_type; - /// **** incoming IF4p5 from remote RCC/RAU **** /// - symbol_number = 0; - symbol_mask = 0; - symbol_mask_full = (1<<(ru->nr_frame_parms->symbols_per_slot))-1; - - do { - recv_IF4p5(ru, frame, slot, &packet_type, &symbol_number); - symbol_mask = symbol_mask | (1<nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int tti_tx,frame_tx; - openair0_timestamp timestamp_tx; - recv_IF5(ru, ×tamp_tx, *slot, IF5_RRH_GW_DL); - // printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); - frame_tx = (timestamp_tx / (fp->samples_per_subframe*10))&1023; - uint32_t idx_sf = timestamp_tx / fp->samples_per_subframe; - tti_tx = (idx_sf * fp->slots_per_subframe + (int)round((float)(timestamp_tx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); - - if (proc->first_tx != 0) { - *slot = tti_tx; - *frame = frame_tx; - proc->first_tx = 0; - } else { - AssertFatal(tti_tx == *slot, - "tti_tx %d is not what we expect %d\n",tti_tx,*slot); - AssertFatal(frame_tx == *frame, - "frame_tx %d is not what we expect %d\n",frame_tx,*frame); - } -} - -void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *slot) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - RU_proc_t *proc = &ru->proc; - uint16_t packet_type; - uint32_t symbol_number,symbol_mask,symbol_mask_full=0; - int slot_tx,frame_tx; - LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru); - symbol_number = 0; - symbol_mask = 0; - - // symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<dl_symbols_in_S_subframe) : (1<symbols_per_slot))-1; - do { - recv_IF4p5(ru, &frame_tx, &slot_tx, &packet_type, &symbol_number); - - if (((nr_slot_select(cfg,frame_tx,slot_tx) & NR_DOWNLINK_SLOT) > 0) && (symbol_number == 0)) start_meas(&ru->rx_fhaul); - - LOG_D(PHY,"slot %d (%d): frame %d, slot %d, symbol %d\n", - *slot,nr_slot_select(cfg,frame_tx,*slot),frame_tx,slot_tx,symbol_number); - - if (proc->first_tx != 0) { - *frame = frame_tx; - *slot = slot_tx; - proc->first_tx = 0; - //symbol_mask_full = ((subframe_select(fp,*slot) == SF_S) ? (1<dl_symbols_in_S_subframe) : (1<symbols_per_slot))-1; - } else { - AssertFatal(frame_tx == *frame, - "frame_tx %d is not what we expect %d\n",frame_tx,*frame); - AssertFatal(slot_tx == *slot, - "slot_tx %d is not what we expect %d\n",slot_tx,*slot); - } - - if (packet_type == IF4p5_PDLFFT) { - symbol_mask = symbol_mask | (1<0) stop_meas(&ru->rx_fhaul); - - proc->tti_tx = slot_tx; - proc->frame_tx = frame_tx; - - if ((frame_tx == 0)&&(slot_tx == 0)) proc->frame_tx_unwrap += 1024; - - proc->timestamp_tx = (((uint64_t)frame_tx + (uint64_t)proc->frame_tx_unwrap) * fp->samples_per_subframe * 10) + fp->get_samples_slot_timestamp(slot_tx, fp, 0); - LOG_D(PHY,"RU %d/%d TST %llu, frame %d, subframe %d\n",ru->idx,0,(long long unsigned int)proc->timestamp_tx,frame_tx,slot_tx); - - // dump VCD output for first RU in list - if (ru == RC.ru[0]) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot_tx ); - } - - if (ru->feptx_ofdm) ru->feptx_ofdm(ru,frame_tx,slot_tx); - - if (ru->fh_south_out) ru->fh_south_out(ru,frame_tx,slot_tx,proc->timestamp_tx); -} - -void fh_if5_north_out(RU_t *ru) { - RU_proc_t *proc=&ru->proc; - uint8_t seqno=0; - /// **** send_IF5 of rxdata to BBU **** /// - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); - send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 ); -} - -// RRU IF4p5 northbound interface (RX) -void fh_if4p5_north_out(RU_t *ru) { - RU_proc_t *proc=&ru->proc; - - //NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - //const int subframe = proc->tti_rx; - if (ru->idx==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); - - /* - if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) { - /// **** in TDD during DL send_IF4 of ULTICK to RCC **** /// - send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULTICK); - return; - }*/ - start_meas(&ru->tx_fhaul); - send_IF4p5(ru, proc->frame_rx, proc->tti_rx, IF4p5_PULFFT); - stop_meas(&ru->tx_fhaul); -} - -void *emulatedRF_thread(void *param) { - RU_proc_t *proc = (RU_proc_t *) param; - int microsec = 500; // length of time to sleep, in miliseconds - struct timespec req = {0}; - req.tv_sec = 0; - req.tv_nsec = (numerology>0)? ((microsec * 1000L)/numerology):(microsec * 1000L)*2; - wait_sync("emulatedRF_thread"); - - while(!oai_exit) { - nanosleep(&req, (struct timespec *)NULL); - pthread_mutex_lock(&proc->mutex_emulateRF); - ++proc->instance_cnt_emulateRF; - pthread_mutex_unlock(&proc->mutex_emulateRF); - pthread_cond_signal(&proc->cond_emulateRF); - } - - return 0; -} - -void rx_rf(RU_t *ru,int *frame,int *slot) { - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - void *rxp[ru->nb_rx]; - unsigned int rxs; - int i; - uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp); - uint32_t samples_per_slot_prev ; - openair0_timestamp ts,old_ts; - AssertFatal(*slotslots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame); - - for (i=0; inb_rx; i++) - rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)]; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); - old_ts = proc->timestamp_rx; - LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]); - - if(emulate_rf) { - wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); - release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread"); - rxs = samples_per_slot; - ts = old_ts + rxs; - } else { - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &ts, - rxp, - samples_per_slot, - ru->nb_rx); - } - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - proc->timestamp_rx = ts-ru->ts_offset; - - //AssertFatal(rxs == fp->samples_per_subframe, - //"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs); - if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",samples_per_slot,rxs); - - if (proc->first_rx == 1) { - ru->ts_offset = proc->timestamp_rx; - proc->timestamp_rx = 0; - } else { - samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp); - if (proc->timestamp_rx - old_ts != samples_per_slot_prev) { - LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot_prev,ru->ts_offset); - ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot_prev); - proc->timestamp_rx = ts-ru->ts_offset; - } - } - - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; - proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx,fp); - // synchronize first reception to frame 0 subframe 0 - LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n", - ru->idx, - 0, - (unsigned long long int)proc->timestamp_rx, - (int)ru->ts_offset,proc->frame_rx,proc->tti_rx,proc->tti_tx,fp->slots_per_frame); - - // dump VCD output for first RU in list - if (ru == RC.ru[0]) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU, proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); - } - - if (proc->first_rx == 0) { - if (proc->tti_rx != *slot) { - LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot); - exit_fun("Exiting"); - } - - if (proc->frame_rx != *frame) { - LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame,proc->tti_rx,*slot); - exit_fun("Exiting"); - } - } else { - proc->first_rx = 0; - *frame = proc->frame_rx; - *slot = proc->tti_rx; - } - - //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); - - if (rxs != samples_per_slot) { - //exit_fun( "problem receiving samples" ); - LOG_E(PHY, "problem receiving samples\n"); - } -} - - -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - void *txp[ru->nb_tx]; - unsigned int txs; - int i,txsymb; - T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot), - T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4)); - - int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); - int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame); - int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame); - int sf_extension = 0; //sf_extension = ru->sf_extension; - int siglen=fp->get_samples_per_slot(slot,fp); - int flags=1; - - //nr_subframe_t SF_type = nr_slot_select(cfg,slot%fp->slots_per_frame); - if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) { - - if (cfg->cell_config.frame_duplex_type.value == TDD){ - if(slot_type == NR_MIXED_SLOT) { - txsymb = 0; - for(int symbol_count = 0; symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) - txsymb++; - } - AssertFatal(txsymb>0,"illegal txsymb %d\n",txsymb); - if(slot%(fp->slots_per_subframe/2)) - siglen = txsymb * (fp->ofdm_symbol_size + fp->nb_prefix_samples); - else - siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); - //+ ru->end_of_burst_delay; - flags = 3; // end of burst - } - - if (slot_type == NR_DOWNLINK_SLOT && prevslot_type == NR_UPLINK_SLOT) - flags = 2; // start of burst - - if (slot_type == NR_DOWNLINK_SLOT && nextslot_type == NR_UPLINK_SLOT) - flags = 3; // end of burst - } - - if (fp->freq_range==nr_FR2) { - // the beam index is written in bits 8-10 of the flags - // bit 11 enables the gpio programming - int beam=0; - //if (slot==0) beam = 11; //3 for boresight & 8 to enable - /* - if (slot==0 || slot==40) beam=0&8; - if (slot==10 || slot==50) beam=1&8; - if (slot==20 || slot==60) beam=2&8; - if (slot==30 || slot==70) beam=3&8; - */ - flags |= beam<<8; - } - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot ); - for (i=0; inb_tx; i++) - txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot,fp,0)-sf_extension]; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); - // prepare tx buffer pointers - txs = ru->rfdevice.trx_write_func(&ru->rfdevice, - timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, - txp, - siglen+sf_extension, - ru->nb_tx, - flags); - LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, slot %di, returned %d\n",ru->idx, - (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot, txs); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); - //AssertFatal(txs == 0,"trx write function error %d\n", txs); - } -} - - - -/*! - * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU. - * This handles the RX FH for an asynchronous RRU/UE - * \param param is a \ref gNB_L1_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_asynch_rxtx( void *param ) { - static int ru_thread_asynch_rxtx_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - int slot=0, frame=0; - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - wait_sync("ru_thread_asynch_rxtx"); - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for devices (ru_thread_asynch_rx)\n"); - wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); - printf( "devices ok (ru_thread_asynch_rx)\n"); - - while (!oai_exit) { - - if (slot==ru->nr_frame_parms->slots_per_frame) { - slot=0; - frame++; - frame&=1023; - } else { - slot++; - } - - LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); - - // asynchronous receive from north (RRU IF4/IF5) - if (ru->fh_north_asynch_in) { - if ((nr_slot_select(cfg,frame,slot) & NR_DOWNLINK_SLOT)>0) - ru->fh_north_asynch_in(ru,&frame,&slot); - } else AssertFatal(1==0,"Unknown function in ru_thread_asynch_rxtx\n"); - } - - ru_thread_asynch_rxtx_status=0; - return(&ru_thread_asynch_rxtx_status); -} - - - - -/*! - * \brief The prach receive thread of RU. - * \param param is a \ref RU_proc_t structure which contains the info what to process. - * \returns a pointer to an int. The storage is not on the heap and must not be freed. - */ -void *ru_thread_prach( void *param ) { - static int ru_thread_prach_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = (RU_proc_t *)&ru->proc; - // set default return value - ru_thread_prach_status = 0; - - while (RC.ru_mask>0) { - usleep(1e6); - LOG_I(PHY,"%s() RACH waiting for RU to be configured\n", __FUNCTION__); - } - - LOG_I(PHY,"%s() RU configured - RACH processing thread running\n", __FUNCTION__); - - while (!oai_exit) { - - - if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - - /*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); - - if (ru->gNB_list[0]){ - prach_procedures( - ru->gNB_list[0],0 - ); - } - else { - rx_prach(NULL, - ru, - NULL, - NULL, - NULL, - proc->frame_prach, - 0,0 - ); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ - if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; - } - - LOG_I(PHY, "Exiting RU thread PRACH\n"); - ru_thread_prach_status = 0; - return &ru_thread_prach_status; -} - - -int wakeup_synch(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - // wake up synch thread - // lock the synch mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU synch thread (IC %d)\n", ru->proc.instance_cnt_synch ); - exit_fun( "error locking mutex_synch" ); - return(-1); - } - - ++ru->proc.instance_cnt_synch; - - // the thread can now be woken up - if (pthread_cond_signal(&ru->proc.cond_synch) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_cond_signal for RU synch thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - - pthread_mutex_unlock( &ru->proc.mutex_synch ); - return(0); -} - -void do_ru_synch(RU_t *ru) { - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - RU_proc_t *proc = &ru->proc; - int i; - void *rxp[2],*rxp2[2]; - int32_t dummy_rx[ru->nb_rx][fp->samples_per_subframe] __attribute__((aligned(32))); - int rxs; - int ic; - - // initialize the synchronization buffer to the common_vars.rxdata - for (int i=0; inb_rx; i++) - rxp[i] = &ru->common.rxdata[i][0]; - - double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0]; - double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0]; - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i]; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); - - while ((ru->in_synch ==0)&&(!oai_exit)) { - // read in frame - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - fp->samples_per_subframe*10, - ru->nb_rx); - - if (rxs != fp->samples_per_subframe*10) LOG_E(PHY,"requested %d samples, got %d\n",fp->samples_per_subframe*10,rxs); - - // wakeup synchronization processing thread - wakeup_synch(ru); - ic=0; - - while ((ic>=0)&&(!oai_exit)) { - // continuously read in frames, 1ms at a time, - // until we are done with the synchronization procedure - for (i=0; inb_rx; i++) - rxp2[i] = (void *)&dummy_rx[i][0]; - - for (i=0; i<10; i++) - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp2, - fp->samples_per_subframe, - ru->nb_rx); - - pthread_mutex_lock(&ru->proc.mutex_synch); - ic = ru->proc.instance_cnt_synch; - pthread_mutex_unlock(&ru->proc.mutex_synch); - } // ic>=0 - } // in_synch==0 - - // read in rx_offset samples - LOG_I(PHY,"Resynchronizing by %d samples\n",ru->rx_offset); - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &(proc->timestamp_rx), - rxp, - ru->rx_offset, - ru->nb_rx); - - for (i=0; i<4; i++) { - ru->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1; - ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq2; - } - - ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); -} - - - -void wakeup_gNB_L1s(RU_t *ru) { - int i; - PHY_VARS_gNB **gNB_list = ru->gNB_list; - LOG_D(PHY,"wakeup_gNB_L1s (num %d) for RU %d ru->gNB_top:%p\n",ru->num_gNB,ru->idx, ru->gNB_top); - - if (ru->num_gNB==1 && ru->gNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { - // call gNB function directly - char string[20]; - sprintf(string,"Incoming RU %u",ru->idx); - LOG_D(PHY,"RU %d Call gNB_top\n",ru->idx); - ru->gNB_top(gNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string,ru); - } else { - LOG_D(PHY,"ru->num_gNB:%d\n", ru->num_gNB); - - for (i=0; inum_gNB; i++) { - LOG_D(PHY,"ru->wakeup_rxtx:%p\n", ru->nr_wakeup_rxtx); - - if (ru->nr_wakeup_rxtx!=0 && ru->nr_wakeup_rxtx(gNB_list[i],ru) < 0) { - LOG_E(PHY,"could not wakeup gNB rxtx process for subframe %d\n", ru->proc.tti_rx); - } - } - } -} - -int wakeup_prach_ru(RU_t *ru) { - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } - - if (ru->proc.instance_cnt_prach==-1) { - ++ru->proc.instance_cnt_prach; - ru->proc.frame_prach = ru->proc.frame_rx; - ru->proc.subframe_prach = ru->proc.tti_rx; - - // DJP - think prach_procedures() is looking at gNB frame_prach - if (ru->gNB_list[0]) { - ru->gNB_list[0]->proc.frame_prach = ru->proc.frame_rx; - ru->gNB_list[0]->proc.slot_prach = ru->proc.tti_rx; - } - - LOG_I(PHY,"RU %d: waking up PRACH thread\n",ru->idx); - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); - } else LOG_W(PHY,"RU prach thread busy, skipping\n"); - - pthread_mutex_unlock( &ru->proc.mutex_prach ); - return(0); -} - -// this is for RU with local RF unit -void fill_rf_config(RU_t *ru, char *rf_config_file) { - int i; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - nfapi_nr_config_request_scf_t *config = &ru->config; //tmp index - openair0_config_t *cfg = &ru->openair0_cfg; - int mu = config->ssb_config.scs_common.value; - int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - - if (mu == NR_MU_0) { //or if LTE - if(N_RB == 100) { - if (fp->threequarter_fs) { - cfg->sample_rate=23.04e6; - cfg->samples_per_frame = 230400; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } else { - cfg->sample_rate=30.72e6; - cfg->samples_per_frame = 307200; - cfg->tx_bw = 10e6; - cfg->rx_bw = 10e6; - } - } else if(N_RB == 50) { - cfg->sample_rate=15.36e6; - cfg->samples_per_frame = 153600; - cfg->tx_bw = 5e6; - cfg->rx_bw = 5e6; - } else if (N_RB == 25) { - cfg->sample_rate=7.68e6; - cfg->samples_per_frame = 76800; - cfg->tx_bw = 2.5e6; - cfg->rx_bw = 2.5e6; - } else if (N_RB == 6) { - cfg->sample_rate=1.92e6; - cfg->samples_per_frame = 19200; - cfg->tx_bw = 1.5e6; - cfg->rx_bw = 1.5e6; - } else AssertFatal(1==0,"Unknown N_RB %d\n",N_RB); - } else if (mu == NR_MU_1) { - if(N_RB == 273) { - if (fp->threequarter_fs) { - AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } - } else if(N_RB == 217) { - if (fp->threequarter_fs) { - cfg->sample_rate=92.16e6; - cfg->samples_per_frame = 921600; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; - } else { - cfg->sample_rate=122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 80e6; - cfg->rx_bw = 80e6; - } - } else if(N_RB == 106) { - if (fp->threequarter_fs) { - cfg->sample_rate=46.08e6; - cfg->samples_per_frame = 460800; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; - } - else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; - } - } else { - AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); - } - } else if (mu == NR_MU_3) { - if (N_RB == 66) { - cfg->sample_rate = 122.88e6; - cfg->samples_per_frame = 1228800; - cfg->tx_bw = 100e6; - cfg->rx_bw = 100e6; - } else if(N_RB == 32) { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 50e6; - cfg->rx_bw = 50e6; - } - } else { - AssertFatal(0 == 1,"Numerology %d not supported for the moment\n",mu); - } - - if (config->cell_config.frame_duplex_type.value==TDD) - cfg->duplex_mode = duplex_mode_TDD; - else //FDD - cfg->duplex_mode = duplex_mode_FDD; - - cfg->Mod_id = 0; - cfg->num_rb_dl=N_RB; - cfg->tx_num_channels=ru->nb_tx; - cfg->rx_num_channels=ru->nb_rx; - - for (i=0; inb_tx; i++) { - if (ru->if_frequency == 0) { - cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; - cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; - } else if (ru->if_freq_offset){ - cfg->tx_freq[i] = (double)(ru->if_frequency); - cfg->rx_freq[i] = (double)(ru->if_frequency + ru->if_freq_offset); - LOG_I(PHY, "Setting IF TX frequency to %lu Hz with IF RX frequency offset %d Hz\n", ru->if_frequency, ru->if_freq_offset); - } else { - cfg->tx_freq[i] = (double)ru->if_frequency; - cfg->rx_freq[i] = (double)(ru->if_frequency+fp->ul_CarrierFreq-fp->dl_CarrierFreq); - } - cfg->tx_gain[i] = ru->att_tx; - cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; - cfg->configFilename = rf_config_file; - LOG_I(PHY, "Channel %d: setting tx_gain offset %f, rx_gain offset %f, tx_freq %lu Hz, rx_freq %lu Hz\n", - i, cfg->tx_gain[i], - cfg->rx_gain[i], - (unsigned long)cfg->tx_freq[i], - (unsigned long)cfg->rx_freq[i]); - } -} - -/* this function maps the RU tx and rx buffers to the available rf chains. - Each rf chain is is addressed by the card number and the chain on the card. The - rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple - antennas are mapped to successive RF chains on the same card. */ -int setup_RU_buffers(RU_t *ru) { - int i,j; - int card,ant; - //uint16_t N_TA_offset = 0; - NR_DL_FRAME_PARMS *frame_parms; - nfapi_nr_config_request_scf_t *config = &ru->config; - - if (ru) { - frame_parms = ru->nr_frame_parms; - printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); - } else { - printf("ru pointer is NULL\n"); - return(-1); - } - int mu = config->ssb_config.scs_common.value; - int N_RB = config->carrier_config.dl_grid_size[config->ssb_config.scs_common.value].value; - - - if (config->cell_config.frame_duplex_type.value == TDD) { - int N_TA_offset = config->carrier_config.uplink_frequency.value < 6000000 ? 400 : 431; // reference samples for 25600Tc @ 30.72 Ms/s for FR1, same @ 61.44 Ms/s for FR2 - - double factor=1; - - switch (mu) { - case 0: //15 kHz scs - AssertFatal(N_TA_offset == 400,"scs_common 15kHz only for FR1\n"); - if (N_RB <= 25) factor = .25; // 7.68 Ms/s - else if (N_RB <=50) factor = .5; // 15.36 Ms/s - else if (N_RB <=75) factor = 1.0; // 30.72 Ms/s - else if (N_RB <=100) factor = 1.0; // 30.72 Ms/s - else AssertFatal(1==0,"Too many PRBS for mu=0\n"); - break; - case 1: //30 kHz sc - AssertFatal(N_TA_offset == 400,"scs_common 30kHz only for FR1\n"); - if (N_RB <= 106) factor = 2.0; // 61.44 Ms/s - else if (N_RB <= 275) factor = 4.0; // 122.88 Ms/s - break; - case 2: //60 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - break; - case 3: //120 kHz scs - AssertFatal(N_TA_offset == 431,"scs_common 120kHz only for FR2\n"); - break; - case 4: //240 kHz scs - AssertFatal(1==0,"scs_common should not be 60 kHz\n"); - if (N_RB <= 32) factor = 1.0; // 61.44 Ms/s - else if (N_RB <= 66) factor = 2.0; // 122.88 Ms/s - else AssertFatal(1==0,"N_RB %d is too big for curretn FR2 implementation\n",N_RB); - break; - - if (N_RB == 100) ru->N_TA_offset = 624; - else if (N_RB == 50) ru->N_TA_offset = 624/2; - else if (N_RB == 25) ru->N_TA_offset = 624/4; - } - if (frame_parms->threequarter_fs == 1) factor = factor*.75; - ru->N_TA_offset = (int)(N_TA_offset * factor); - LOG_I(PHY,"RU %d Setting N_TA_offset to %d samples (factor %f, UL Freq %d, N_RB %d)\n",ru->idx,ru->N_TA_offset,factor, - config->carrier_config.uplink_frequency.value, N_RB); - } - else ru->N_TA_offset = 0; - - - if (ru->openair0_cfg.mmapped_dma == 1) { - // replace RX signal buffers with mmaped HW versions - for (i=0; inb_rx; i++) { - card = i/4; - ant = i%4; - printf("Mapping RU id %u, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); - free(ru->common.rxdata[i]); - ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain+ant]; - printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); - - for (j=0; j<16; j++) { - printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); - ru->common.rxdata[i][j] = 16-j; - } - } - - for (i=0; inb_tx; i++) { - card = i/4; - ant = i%4; - printf("Mapping RU id %u, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); - free(ru->common.txdata[i]); - ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant]; - printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); - - for (j=0; j<16; j++) { - printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); - ru->common.txdata[i][j] = 16-j; - } - } - } else { // not memory-mapped DMA - //nothing to do, everything already allocated in lte_init - } - - return(0); -} - -void *ru_stats_thread(void *param) { - RU_t *ru = (RU_t *)param; - wait_sync("ru_stats_thread"); - - while (!oai_exit) { - sleep(1); - - if (opp_enabled == 1) { - - if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); - - if (ru->feptx_ofdm) { - print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL); - print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); - print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); - print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL); - } - - if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); - - print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); - if (ru->fh_north_out) { - print_meas(&ru->compression,"compression",NULL,NULL); - print_meas(&ru->transport,"transport",NULL,NULL); - } - } - } - - return(NULL); -} - -void *ru_thread_tx( void *param ) { - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - PHY_VARS_gNB *gNB; - gNB_L1_proc_t *gNB_proc; - gNB_L1_rxtx_proc_t *L1_proc; - char filename[40]; - int print_frame = 8; - int i = 0; - int ret; - - - wait_on_condition(&proc->mutex_FH1,&proc->cond_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - printf( "ru_thread_tx ready\n"); - - while (!oai_exit) { - - LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n"); - // wait until eNBs are finished subframe RX n and TX n+4 - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 ); - wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 ); - - ret = pthread_mutex_lock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock return %d\n",ret); - int frame_tx=proc->frame_tx; - int tti_tx =proc->tti_tx; - uint64_t timestamp_tx = proc->timestamp_tx; - - ret = pthread_mutex_unlock(&proc->mutex_gNBs); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - - if (oai_exit) break; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, tti_tx ); - - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx); - - if(!emulate_rf) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,frame_tx,tti_tx,timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - - if(proc->tti_tx == 0) { - sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1); - - sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1); - } - - if(proc->tti_tx == 9) { - sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); - LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); - sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); - FILE *output_fd = fopen(filename,"w"); - - if (output_fd) { - fwrite(&ru->common.txdata[i][0], - sizeof(int32_t), - fp->samples_per_frame, - output_fd); - fclose(output_fd); - } else { - LOG_E(PHY,"Cannot write to file %s\n",filename); - } - }//if(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - release_thread(&proc->mutex_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx"); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, proc->instance_cnt_gNBs); - - for(i = 0; inum_gNB; i++) { - gNB = ru->gNB_list[i]; - gNB_proc = &gNB->proc; - L1_proc = (get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT)? &gNB_proc->L1_proc_tx : &gNB_proc->L1_proc; - ret = pthread_mutex_lock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - - for (int j=0; jnum_RU; j++) { - if (ru == gNB->RU_list[j]) { - if ((gNB_proc->RU_mask_tx&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU tx %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,gNB_proc->frame_rx,gNB_proc->slot_rx,ru->idx,gNB->num_RU,gNB_proc->RU_mask_tx); - - gNB_proc->RU_mask_tx |= (1<RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } else { // all RUs TX are finished so send the ready signal to gNB processing - gNB_proc->RU_mask_tx = 0; - ret = pthread_mutex_unlock(&gNB_proc->mutex_RU_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - - ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_lock returns %d\n",ret); - // the thread can now be woken up - if (L1_proc->instance_cnt_RUs == -1) { - L1_proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); - AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, - "ERROR pthread_cond_signal for gNB_L1_thread\n"); - } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); - ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); - AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); - } - } - } - - release_thread(&proc->mutex_FH1,&proc->instance_cnt_FH1,"ru_thread_tx"); - return 0; -} - -void *ru_thread( void *param ) { - static int ru_thread_status; - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - int ret; - int slot = fp->slots_per_frame-1; - int frame = 1023; - char filename[40], threadname[40]; - int print_frame = 8; - int i = 0; - int aa; - - nfapi_nr_config_request_scf_t *cfg = &ru->config; - - // set default return value - ru_thread_status = 0; - // set default return value - sprintf(threadname,"ru_thread %u",ru->idx); - - - LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); - - memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); - - if(emulate_rf) { - fill_rf_config(ru,ru->rf_config_file); - nr_init_frame_parms(&ru->config, fp); - nr_dump_frame_parms(fp); - nr_phy_init_RU(ru); - - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } - } else { - // Start IF device if any - if (ru->nr_start_if) { - LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx); - AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n"); - - if (ru->if_south == LOCAL_RF) ret = connect_rau(ru); - else ret = attach_rru(ru); - - AssertFatal(ret==0,"Cannot connect to remote radio\n"); - } - - if (ru->if_south == LOCAL_RF) { // configure RF parameters only - nr_init_frame_parms(&ru->config, fp); - nr_dump_frame_parms(fp); - fill_rf_config(ru,ru->rf_config_file); - nr_phy_init_RU(ru); - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - AssertFatal(ret==0,"Cannot connect to local radio\n"); - } - - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } - } - - sf_ahead = (uint16_t) ceil((float)6/(0x01<numerology_index)); - LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); - pthread_mutex_lock(&RC.ru_mutex); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - pthread_mutex_unlock(&RC.ru_mutex); - wait_sync("ru_thread"); - - if(!emulate_rf) { - // Start RF device if any - if (ru->start_rf) { - if (ru->start_rf(ru) != 0) - LOG_E(HW,"Could not start the RF device\n"); - else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); - } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); - - // if an asnych_rxtx thread exists - // wakeup the thread because the devices are ready at this point - - if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) { - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx=0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); - } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); - - // if this is a slave RRU, try to synchronize on the DL frequency - if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); - - // start trx write thread - if(usrp_tx_thread == 1){ - if (ru->start_write_thread){ - if(ru->start_write_thread(ru) != 0){ - LOG_E(HW,"Could not start tx write thread\n"); - } - else{ - LOG_I(PHY,"tx write thread ready\n"); - } - } - } - } - - pthread_mutex_lock(&proc->mutex_FH1); - proc->instance_cnt_FH1 = 0; - pthread_mutex_unlock(&proc->mutex_FH1); - pthread_cond_signal(&proc->cond_FH1); - - // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices - while (!oai_exit) { - // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. - // They are set on the first rx/tx in the underly FH routines. - if (slot==(fp->slots_per_frame-1)) { - slot=0; - frame++; - frame&=1023; - } else { - slot++; - } - - // synchronization on input FH interface, acquire signals/data and block - LOG_D(PHY,"[RU_thread] read data: frame_rx = %d, tti_rx = %d\n", frame, slot); - if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot); - else AssertFatal(1==0, "No fronthaul interface at south port"); - - LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", - frame,slot, - proc->frame_rx,proc->tti_rx, - proc->frame_tx,proc->tti_tx, - RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx, - RC.gNB[0]->proc.frame_tx); - /* - LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", - ru->do_prach, - is_prach_subframe(fp, proc->frame_rx, proc->tti_rx), - proc->frame_rx,proc->tti_rx); - - if ((ru->do_prach>0) && (is_prach_subframe(fp, proc->frame_rx, proc->tti_rx)==1)) { - wakeup_prach_ru(ru); - }*/ - - // adjust for timing offset between RU - //printf("~~~~~~~~~~~~~~~~~~~~~~~~~~%d.%d in ru_thread is in process\n", proc->frame_rx, proc->tti_rx); - if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; - - // do RX front-end processing (frequency-shift, dft) if needed - - int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); - if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { - //if (proc->tti_rx==8) { - - if (ru->feprx) { - ru->feprx(ru,proc->tti_rx); - //LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1); - - LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); - LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); - - for (aa=0;aanb_rx;aa++) - memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa], - (void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); - - // Do PRACH RU processing - - int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); - uint8_t prachStartSymbol,N_dur; - if (prach_id>=0) { - N_dur = get_nr_prach_duration(ru->prach_list[prach_id].fmt); - /* - get_nr_prach_info_from_index(ru->config.prach_config.prach_ConfigurationIndex.value, - proc->frame_rx,proc->tti_rx, - ru->config.carrier_config.dl_frequency.value, - fp->numerology_index, - fp->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &RA_sfn_index, - &N_RA_slot, - &config_period); - */ - for (int prach_oc = 0; prach_ocprach_list[prach_id].num_prach_ocas; prach_oc++) { - prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol+prach_oc*N_dur; - //comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}. - - rx_nr_prach_ru(ru, - ru->prach_list[prach_id].fmt, //could also use format - ru->prach_list[prach_id].numRA, - prachStartSymbol, - prach_oc, - proc->frame_rx,proc->tti_rx); - } - free_nr_ru_prach_entry(ru,prach_id); - } - } - } - - // At this point, all information for subframe has been received on FH interface - - // wakeup all gNB processes waiting for this RU - if (ru->num_gNB>0) wakeup_gNB_L1s(ru); - - if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_gNB==0) { - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx); - - // do OFDM with/without TX front-end processing if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx); - - if(!emulate_rf) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru,proc->frame_tx,proc->tti_tx,proc->timestamp_tx); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } else { - if(proc->frame_tx == print_frame) { - for (i=0; inb_tx; i++) { - sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx); - LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_slot_wCP, 1, 1); - - if(proc->tti_tx == 9) { - sprintf(filename,"tx%ddata_frame%d.m", i, print_frame); - LOG_M(filename,"txdata_frame",&ru->common.txdata[i][0],fp->samples_per_frame, 1, 1); - sprintf(filename,"tx%ddata_frame%d.dat", i, print_frame); - FILE *output_fd = fopen(filename,"w"); - - if (output_fd) { - fwrite(&ru->common.txdata[i][0], - sizeof(int32_t), - fp->samples_per_frame, - output_fd); - fclose(output_fd); - } else { - LOG_E(PHY,"Cannot write to file %s\n",filename); - } - }//if(proc->tti_tx == 9) - }//for (i=0; inb_tx; i++) - }//if(proc->frame_tx == print_frame) - }//else emulate_rf - - proc->emulate_rf_busy = 0; - }//if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) - } - - printf( "Exiting ru_thread \n"); - - if (ru->stop_rf != NULL) { - if (ru->stop_rf(ru) != 0) - LOG_E(HW,"Could not stop the RF device\n"); - else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); - } - - ru_thread_status = 0; - return &ru_thread_status; -} -/* -// This thread run the initial synchronization like a UE -void *ru_thread_synch(void *arg) { - - RU_t *ru = (RU_t*)arg; - NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; - int32_t sync_pos,sync_pos2; - uint32_t peak_val; - uint32_t sync_corr[307200] __attribute__((aligned(32))); - static int ru_thread_synch_status; - - - - wait_sync("ru_thread_synch"); - - // initialize variables for PSS detection - lte_sync_time_init(ru->nr_frame_parms); - - while (!oai_exit) { - - // wait to be woken up - if (wait_on_condition(&ru->proc.mutex_synch,&ru->proc.cond_synch,&ru->proc.instance_cnt_synch,"ru_thread_synch")<0) break; - - // if we're not in synch, then run initial synch - if (ru->in_synch == 0) { - // run intial synch like UE - LOG_I(PHY,"Running initial synchronization\n"); - - sync_pos = lte_sync_time_gNB(ru->common.rxdata, - fp, - fp->samples_per_subframe*5, - &peak_val, - sync_corr); - LOG_I(PHY,"RU synch: %d, val %d\n",sync_pos,peak_val); - - if (sync_pos >= 0) { - if (sync_pos >= fp->nb_prefix_samples) - sync_pos2 = sync_pos - fp->nb_prefix_samples; - else - sync_pos2 = sync_pos + (fp->samples_per_subframe*10) - fp->nb_prefix_samples; - - if (fp->frame_type == FDD) { - - // PSS is hypothesized in last symbol of first slot in Frame - int sync_pos_slot = (fp->samples_per_subframe>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples; - - if (sync_pos2 >= sync_pos_slot) - ru->rx_offset = sync_pos2 - sync_pos_slot; - else - ru->rx_offset = (fp->samples_per_subframe*10) + sync_pos2 - sync_pos_slot; - } - else { - - } - - LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,ru->rx_offset); - - if ((peak_val > 300000) && (sync_pos > 0)) { - // if (sync_pos++ > 3) { - write_output("ru_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_subframe*5,1,2); - write_output("ru_rx.m","rxs",(void*)ru->ru_time.rxdata[0][0],fp->samples_per_subframe*10,1,1); - exit(-1); - } - - ru->in_synch=1; - } - } - - if (release_thread(&ru->proc.mutex_synch,&ru->proc.instance_cnt_synch,"ru_synch_thread") < 0) break; - } // oai_exit - - ru_thread_synch_status = 0; - return &ru_thread_synch_status; - -} -*/ - -int nr_start_if(struct RU_t_s *ru, struct PHY_VARS_gNB_s *gNB) { - return(ru->ifdevice.trx_start_func(&ru->ifdevice)); -} - -int start_rf(RU_t *ru) { - return(ru->rfdevice.trx_start_func(&ru->rfdevice)); -} - -int stop_rf(RU_t *ru) { - ru->rfdevice.trx_end_func(&ru->rfdevice); - return 0; -} - -int start_write_thread(RU_t *ru) { - return(ru->rfdevice.trx_write_init(&ru->rfdevice)); -} - -void init_RU_proc(RU_t *ru) { - int i=0; - RU_proc_t *proc; - char name[100]; - LOG_I(PHY,"Initializing RU proc %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]); - proc = &ru->proc; - memset((void *)proc,0,sizeof(RU_proc_t)); - proc->ru = ru; - proc->instance_cnt_prach = -1; - proc->instance_cnt_synch = -1; - proc->instance_cnt_FH = -1; - proc->instance_cnt_FH1 = -1; - proc->instance_cnt_gNBs = -1; - proc->instance_cnt_asynch_rxtx = -1; - proc->instance_cnt_emulateRF = -1; - proc->first_rx = 1; - proc->first_tx = 1; - proc->frame_offset = 0; - proc->num_slaves = 0; - proc->frame_tx_unwrap = 0; - proc->feptx_mask = 0; - - for (i=0; i<10; i++) proc->symbol_mask[i]=0; - - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); - pthread_mutex_init( &proc->mutex_synch,NULL); - pthread_mutex_init( &proc->mutex_FH,NULL); - pthread_mutex_init( &proc->mutex_FH1,NULL); - pthread_mutex_init( &proc->mutex_emulateRF,NULL); - pthread_mutex_init( &proc->mutex_gNBs, NULL); - pthread_cond_init( &proc->cond_prach, NULL); - pthread_cond_init( &proc->cond_FH, NULL); - pthread_cond_init( &proc->cond_FH1, NULL); - pthread_cond_init( &proc->cond_emulateRF, NULL); - pthread_cond_init( &proc->cond_asynch_rxtx, NULL); - pthread_cond_init( &proc->cond_synch,NULL); - pthread_cond_init( &proc->cond_gNBs, NULL); - threadCreate( &proc->pthread_FH, ru_thread, (void *)ru, "thread_FH", -1, OAI_PRIORITY_RT_MAX ); - - if (get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) - threadCreate( &proc->pthread_FH1, ru_thread_tx, (void *)ru, "thread_FH1", -1, OAI_PRIORITY_RT ); - - if(emulate_rf) - threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); - - if (ru->function == NGFI_RRU_IF4p5) { - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru, "RACH", -1, OAI_PRIORITY_RT ); - ///tmp deactivation of synch thread - // if (ru->is_slave == 1) pthread_create( &proc->pthread_synch, attr_synch, ru_thread_synch, (void*)ru); - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) threadCreate( &proc->pthread_asynch_rxtx, ru_thread_asynch_rxtx, (void *)ru, "asynch_rxtx", -1, OAI_PRIORITY_RT ); - - snprintf( name, sizeof(name), "ru_thread_FH %d", ru->idx ); - pthread_setname_np( proc->pthread_FH, name ); - } else if (ru->function == gNodeB_3GPP && ru->if_south == LOCAL_RF) { // DJP - need something else to distinguish between monolithic and PNF - LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); - threadCreate( &proc->pthread_prach, ru_thread_prach, (void *)ru,"RACH", -1, OAI_PRIORITY_RT ); - } - - if (get_thread_worker_conf() == WORKER_ENABLE) { - if (ru->feprx) nr_init_feprx_thread(ru); - - if (ru->feptx_ofdm) nr_init_feptx_thread(ru); - } - - if (opp_enabled == 1) threadCreate(&ru->ru_stats_thread,ru_stats_thread,(void *)ru, "emulateRF", -1, OAI_PRIORITY_RT_LOW); -} - -void kill_NR_RU_proc(int inst) { - RU_t *ru = RC.ru[inst]; - RU_proc_t *proc = &ru->proc; - pthread_mutex_lock(&proc->mutex_FH); - proc->instance_cnt_FH = 0; - pthread_mutex_unlock(&proc->mutex_FH); - pthread_cond_signal(&proc->cond_FH); - pthread_mutex_lock(&proc->mutex_prach); - proc->instance_cnt_prach = 0; - pthread_mutex_unlock(&proc->mutex_prach); - pthread_cond_signal(&proc->cond_prach); - pthread_mutex_lock(&proc->mutex_synch); - proc->instance_cnt_synch = 0; - pthread_mutex_unlock(&proc->mutex_synch); - pthread_cond_signal(&proc->cond_synch); - pthread_mutex_lock(&proc->mutex_gNBs); - proc->instance_cnt_gNBs = 0; - pthread_mutex_unlock(&proc->mutex_gNBs); - pthread_cond_signal(&proc->cond_gNBs); - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->instance_cnt_asynch_rxtx = 0; - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); - pthread_cond_signal(&proc->cond_asynch_rxtx); - LOG_D(PHY, "Joining pthread_FH\n"); - pthread_join(proc->pthread_FH, NULL); - - if (ru->function == NGFI_RRU_IF4p5) { - LOG_D(PHY, "Joining pthread_prach\n"); - pthread_join(proc->pthread_prach, NULL); - - if (ru->is_slave) { - LOG_D(PHY, "Joining pthread_\n"); - pthread_join(proc->pthread_synch, NULL); - } - - if ((ru->if_timing == synch_to_other) || - (ru->function == NGFI_RRU_IF5) || - (ru->function == NGFI_RRU_IF4p5)) { - LOG_D(PHY, "Joining pthread_asynch_rxtx\n"); - pthread_join(proc->pthread_asynch_rxtx, NULL); - } - } - - if (get_nprocs() >= 2) { - if (ru->feprx) { - pthread_mutex_lock(&proc->mutex_fep); - proc->instance_cnt_fep = 0; - pthread_mutex_unlock(&proc->mutex_fep); - pthread_cond_signal(&proc->cond_fep); - LOG_D(PHY, "Joining pthread_fep\n"); - pthread_join(proc->pthread_fep, NULL); - pthread_mutex_destroy(&proc->mutex_fep); - pthread_cond_destroy(&proc->cond_fep); - } - - if (ru->feptx_ofdm) { - pthread_mutex_lock(&proc->mutex_feptx); - proc->instance_cnt_feptx = 0; - pthread_mutex_unlock(&proc->mutex_feptx); - pthread_cond_signal(&proc->cond_feptx); - LOG_D(PHY, "Joining pthread_feptx\n"); - pthread_join(proc->pthread_feptx, NULL); - pthread_mutex_destroy(&proc->mutex_feptx); - pthread_cond_destroy(&proc->cond_feptx); - } - } - - if (opp_enabled) { - LOG_D(PHY, "Joining ru_stats_thread\n"); - pthread_join(ru->ru_stats_thread, NULL); - } - - pthread_mutex_destroy(&proc->mutex_prach); - pthread_mutex_destroy(&proc->mutex_asynch_rxtx); - pthread_mutex_destroy(&proc->mutex_synch); - pthread_mutex_destroy(&proc->mutex_FH); - pthread_mutex_destroy(&proc->mutex_gNBs); - pthread_cond_destroy(&proc->cond_prach); - pthread_cond_destroy(&proc->cond_FH); - pthread_cond_destroy(&proc->cond_asynch_rxtx); - pthread_cond_destroy(&proc->cond_synch); - pthread_cond_destroy(&proc->cond_gNBs); -} - -int check_capabilities(RU_t *ru,RRU_capabilities_t *cap) -{ - FH_fmt_options_t fmt = cap->FH_fmt; - int i; - int found_band=0; - LOG_I(PHY,"RRU %d, num_bands %d, looking for band %d\n",ru->idx,cap->num_bands,ru->nr_frame_parms->nr_band); - - for (i=0; inum_bands; i++) { - LOG_I(PHY,"band %d on RRU %d\n",cap->band_list[i],ru->idx); - - if (ru->nr_frame_parms->nr_band == cap->band_list[i]) { - found_band=1; - break; - } - } - - if (found_band == 0) { - LOG_I(PHY,"Couldn't find target NR band %d on RRU %d\n",ru->nr_frame_parms->nr_band,ru->idx); - return(-1); - } - - switch (ru->if_south) { - case LOCAL_RF: - AssertFatal(1==0, "This RU should not have a local RF, exiting\n"); - return(0); - break; - - case REMOTE_IF5: - if (fmt == OAI_IF5_only || fmt == OAI_IF5_and_IF4p5) return(0); - - break; - - case REMOTE_IF4p5: - if (fmt == OAI_IF4p5_only || fmt == OAI_IF5_and_IF4p5) return(0); - - break; - - case REMOTE_MBP_IF5: - if (fmt == MBP_IF5) return(0); - - break; - - default: - LOG_I(PHY,"No compatible Fronthaul interface found for RRU %d\n", ru->idx); - return(-1); - } - - return(-1); -} - - -char rru_format_options[4][20] = {"OAI_IF5_only","OAI_IF4p5_only","OAI_IF5_and_IF4p5","MBP_IF5"}; - -char rru_formats[3][20] = {"OAI_IF5","MBP_IF5","OAI_IF4p5"}; -char ru_if_formats[4][20] = {"LOCAL_RF","REMOTE_OAI_IF5","REMOTE_MBP_IF5","REMOTE_OAI_IF4p5"}; - -void configure_ru(int idx, - void *arg) -{ - RU_t *ru = RC.ru[idx]; - RRU_config_t *config = (RRU_config_t *)arg; - RRU_capabilities_t *capabilities = (RRU_capabilities_t *)arg; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - int ret; - LOG_I(PHY, "Received capabilities from RRU %d\n",idx); - - if (capabilities->FH_fmt < MAX_FH_FMTs) LOG_I(PHY, "RU FH options %s\n",rru_format_options[capabilities->FH_fmt]); - - ret = check_capabilities(ru,capabilities); - AssertFatal(ret == 0, "Cannot configure RRU %d, check_capabilities returned %d\n", idx, ret); - // take antenna capabilities of RRU - ru->nb_tx = capabilities->nb_tx[0]; - ru->nb_rx = capabilities->nb_rx[0]; - // Pass configuration to RRU - LOG_I(PHY, "Using %s fronthaul (%d), band %d \n",ru_if_formats[ru->if_south],ru->if_south,ru->nr_frame_parms->nr_band); - // wait for configuration - config->FH_fmt = ru->if_south; - config->num_bands = 1; - config->band_list[0] = ru->nr_frame_parms->nr_band; - config->tx_freq[0] = ru->nr_frame_parms->dl_CarrierFreq; - config->rx_freq[0] = ru->nr_frame_parms->ul_CarrierFreq; - //config->tdd_config[0] = ru->nr_frame_parms->tdd_config; - //config->tdd_config_S[0] = ru->nr_frame_parms->tdd_config_S; - config->att_tx[0] = ru->att_tx; - config->att_rx[0] = ru->att_rx; - config->N_RB_DL[0] = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value; - config->N_RB_UL[0] = cfg->carrier_config.dl_grid_size[cfg->ssb_config.scs_common.value].value; - config->threequarter_fs[0] = ru->nr_frame_parms->threequarter_fs; - /* if (ru->if_south==REMOTE_IF4p5) { - config->prach_FreqOffset[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset; - config->prach_ConfigIndex[0] = ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex; - LOG_I(PHY,"REMOTE_IF4p5: prach_FrequOffset %d, prach_ConfigIndex %d\n", - config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);*/ - nr_init_frame_parms(&ru->config, ru->nr_frame_parms); - nr_phy_init_RU(ru); -} - -void configure_rru(int idx, - void *arg) { - RRU_config_t *config = (RRU_config_t *)arg; - RU_t *ru = RC.ru[idx]; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - ru->nr_frame_parms->nr_band = config->band_list[0]; - ru->nr_frame_parms->dl_CarrierFreq = config->tx_freq[0]; - ru->nr_frame_parms->ul_CarrierFreq = config->rx_freq[0]; - - if (ru->nr_frame_parms->dl_CarrierFreq == ru->nr_frame_parms->ul_CarrierFreq) { - cfg->cell_config.frame_duplex_type.value = TDD; - //ru->nr_frame_parms->tdd_config = config->tdd_config[0]; - //ru->nr_frame_parms->tdd_config_S = config->tdd_config_S[0]; - } else - cfg->cell_config.frame_duplex_type.value = FDD; - - ru->att_tx = config->att_tx[0]; - ru->att_rx = config->att_rx[0]; - int mu = cfg->ssb_config.scs_common.value; - cfg->carrier_config.dl_grid_size[mu].value = config->N_RB_DL[0]; - cfg->carrier_config.dl_grid_size[mu].value = config->N_RB_UL[0]; - ru->nr_frame_parms->threequarter_fs = config->threequarter_fs[0]; - - //ru->nr_frame_parms->pdsch_config_common.referenceSignalPower = ru->max_pdschReferenceSignalPower-config->att_tx[0]; - if (ru->function==NGFI_RRU_IF4p5) { - ru->nr_frame_parms->att_rx = ru->att_rx; - ru->nr_frame_parms->att_tx = ru->att_tx; - /* - LOG_I(PHY,"Setting ru->function to NGFI_RRU_IF4p5, prach_FrequOffset %d, prach_ConfigIndex %d, att (%d,%d)\n", - config->prach_FreqOffset[0],config->prach_ConfigIndex[0],ru->att_tx,ru->att_rx); - ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset = config->prach_FreqOffset[0]; - ru->nr_frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = config->prach_ConfigIndex[0]; */ - } - - fill_rf_config(ru,ru->rf_config_file); - nr_init_frame_parms(&ru->config, ru->nr_frame_parms); - nr_phy_init_RU(ru); -} - -/* -void init_precoding_weights(PHY_VARS_gNB *gNB) { - - int layer,ru_id,aa,re,ue,tb; - LTE_DL_FRAME_PARMS *fp=&gNB->frame_parms; - RU_t *ru; - LTE_gNB_DLSCH_t *dlsch; - - // init precoding weigths - for (ue=0;uedlsch[ue][tb]; - for (layer=0; layer<4; layer++) { - int nb_tx=0; - for (ru_id=0;ru_idnb_tx; - } - dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(nb_tx*sizeof(int32_t*)); - - for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); - for (re=0;reofdm_symbol_size; re++) { - dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; - } - } - } - } - } -}*/ - -void set_function_spec_param(RU_t *ru) { - int ret; - - switch (ru->if_south) { - case LOCAL_RF: // this is an RU with integrated RF (RRU, gNB) - if (ru->function == NGFI_RRU_IF5) { // IF5 RRU - ru->do_prach = 0; // no prach processing in RU - ru->fh_north_in = NULL; // no shynchronous incoming fronthaul from north - ru->fh_north_out = fh_if5_north_out; // need only to do send_IF5 reception - ru->fh_south_out = tx_rf; // send output to RF - ru->fh_north_asynch_in = fh_if5_north_asynch_in; // TX packets come asynchronously - ru->feprx = NULL; // nothing (this is a time-domain signal) - ru->feptx_ofdm = NULL; // nothing (this is a time-domain signal) - ru->feptx_prec = NULL; // nothing (this is a time-domain signal) - ru->nr_start_if = nr_start_if; // need to start the if interface for if5 - ru->ifdevice.host_type = RRU_HOST; - ru->rfdevice.host_type = RRU_HOST; - ru->ifdevice.eth_params = &ru->eth_params; - reset_meas(&ru->rx_fhaul); - reset_meas(&ru->tx_fhaul); - reset_meas(&ru->compression); - reset_meas(&ru->transport); - ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); - - if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - } else if (ru->function == NGFI_RRU_IF4p5) { - ru->do_prach = 1; // do part of prach processing in RU - ru->fh_north_in = NULL; // no synchronous incoming fronthaul from north - ru->fh_north_out = fh_if4p5_north_out; // send_IF4p5 on reception - ru->fh_south_out = tx_rf; // send output to RF - ru->fh_north_asynch_in = fh_if4p5_north_asynch_in; // TX packets come asynchronously - ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // RX DFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft only (no precoding in RRU) - ru->feptx_prec = NULL; - ru->nr_start_if = nr_start_if; // need to start the if interface for if4p5 - ru->ifdevice.host_type = RRU_HOST; - ru->rfdevice.host_type = RRU_HOST; - ru->ifdevice.eth_params = &ru->eth_params; - reset_meas(&ru->rx_fhaul); - reset_meas(&ru->tx_fhaul); - reset_meas(&ru->compression); - reset_meas(&ru->transport); - ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); - - if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - - malloc_IF4p5_buffer(ru); - } else if (ru->function == gNodeB_3GPP) { - ru->do_prach = 0; // no prach processing in RU - ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // RX DFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft and precoding - ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // this is fep with idft and precoding - ru->fh_north_in = NULL; // no incoming fronthaul from north - ru->fh_north_out = NULL; // no outgoing fronthaul to north - ru->nr_start_if = NULL; // no if interface - ru->rfdevice.host_type = RAU_HOST; - - // FK this here looks messed up. The following lines should be part of the if (ru->function == gNodeB_3GPP), shouldn't they? - - ru->fh_south_in = rx_rf; // local synchronous RF RX - ru->fh_south_out = tx_rf; // local synchronous RF TX - ru->start_rf = start_rf; // need to start the local RF interface - ru->stop_rf = stop_rf; - ru->start_write_thread = start_write_thread; // starting RF TX in different thread - printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); - } - - /* - printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf); - fill_rf_config(ru,rf_config_file); - init_frame_parms(&ru->frame_parms,1); - nr_phy_init_RU(ru); - - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } - */ - break; - - case REMOTE_IF5: // the remote unit is IF5 RRU - ru->do_prach = 0; - ru->feprx = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full; // this is frequency-shift + DFTs - ru->feptx_prec = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec; // need to do transmit Precoding + IDFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // need to do transmit Precoding + IDFTs - ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception - ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission - ru->fh_south_asynch_in = NULL; // no asynchronous UL - ru->start_rf = NULL; // no local RF - ru->stop_rf = NULL; - ru->start_write_thread = NULL; - ru->nr_start_if = nr_start_if; // need to start if interface for IF5 - ru->ifdevice.host_type = RAU_HOST; - ru->ifdevice.eth_params = &ru->eth_params; - ru->ifdevice.configure_rru = configure_ru; - ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); - - if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - - break; - - case REMOTE_IF4p5: - ru->do_prach = 0; - ru->feprx = NULL; // DFTs - ru->feptx_prec = nr_feptx_prec; // Precoding operation - ru->feptx_ofdm = NULL; // no OFDM mod - ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception - ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission - ru->fh_south_asynch_in = (ru->if_timing == synch_to_other) ? fh_if4p5_south_in : NULL; // asynchronous UL if synch_to_other - ru->fh_north_out = NULL; - ru->fh_north_asynch_in = NULL; - ru->start_rf = NULL; // no local RF - ru->stop_rf = NULL; - ru->start_write_thread = NULL; - ru->nr_start_if = nr_start_if; // need to start if interface for IF4p5 - ru->ifdevice.host_type = RAU_HOST; - ru->ifdevice.eth_params = &ru->eth_params; - ru->ifdevice.configure_rru = configure_ru; - ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %u\n", ret, ru->idx); - - if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - - if (ru->ifdevice.get_internal_parameter != NULL) { - void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in"); - if (t != NULL) - ru->fh_south_in = t; - t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out"); - if (t != NULL) - ru->fh_south_out = t; - } - - malloc_IF4p5_buffer(ru); - break; - - default: - LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); - break; - } // switch on interface type -} - -void init_NR_RU(char *rf_config_file) -{ - int ru_id; - RU_t *ru; - PHY_VARS_gNB *gNB_RC; - PHY_VARS_gNB *gNB0= (PHY_VARS_gNB *)NULL; - NR_DL_FRAME_PARMS *fp = (NR_DL_FRAME_PARMS *)NULL; - int i; - // create status mask - RC.ru_mask = 0; - pthread_mutex_init(&RC.ru_mutex,NULL); - pthread_cond_init(&RC.ru_cond,NULL); - // read in configuration file) - printf("configuring RU from file\n"); - RCconfig_RU(); - LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_nr_L1_inst,RC.nb_RU,get_nprocs()); - - LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); - - for (ru_id=0; ru_idrf_config_file = rf_config_file; - ru->idx = ru_id; - ru->ts_offset = 0; - // use gNB_list[0] as a reference for RU frame parameters - // NOTE: multiple CC_id are not handled here yet! - - if (ru->num_gNB > 0) { - LOG_D(PHY, "%s() RC.ru[%d].num_gNB:%d ru->gNB_list[0]:%p RC.gNB[0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_gNB, ru->gNB_list[0], RC.gNB[0], ru->rf_config_file); - - if (ru->gNB_list[0] == 0) { - LOG_E(PHY,"%s() DJP - ru->gNB_list ru->num_gNB are not initialized - so do it manually\n", __FUNCTION__); - ru->gNB_list[0] = RC.gNB[0]; - ru->num_gNB=1; - // - // DJP - feptx_prec() / feptx_ofdm() parses the gNB_list (based on num_gNB) and copies the txdata_F to txdata in RU - // - } else { - LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__); - } - } - - gNB_RC = RC.gNB[0]; - gNB0 = ru->gNB_list[0]; - fp = ru->nr_frame_parms; - LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south); - - if (gNB0) { - if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5)) - AssertFatal(gNB0!=NULL,"gNB0 is null!\n"); - - if (gNB0 && gNB_RC) { - LOG_I(PHY,"Copying frame parms from gNB in RC to gNB %d in ru %d and frame_parms in ru\n",gNB0->Mod_id,ru->idx); - memset((void *)fp, 0, sizeof(NR_DL_FRAME_PARMS)); - memcpy((void *)fp,&gNB_RC->frame_parms,sizeof(NR_DL_FRAME_PARMS)); - memcpy((void *)&gNB0->frame_parms,(void *)&gNB_RC->frame_parms,sizeof(NR_DL_FRAME_PARMS)); - // attach all RU to all gNBs in its list/ - LOG_D(PHY,"ru->num_gNB:%d gNB0->num_RU:%d\n", ru->num_gNB, gNB0->num_RU); - - for (i=0; inum_gNB; i++) { - gNB0 = ru->gNB_list[i]; - gNB0->RU_list[gNB0->num_RU++] = ru; - } - } - } - - //LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],NB_timing[ru->if_timing],ru->function); - set_function_spec_param(ru); - LOG_I(PHY,"Starting ru_thread %d\n",ru_id); - init_RU_proc(ru); - } // for ru_id - - // sleep(1); - LOG_D(HW,"[nr-softmodem.c] RU threads created\n"); -} - - -void stop_RU(int nb_ru) -{ - for (int inst = 0; inst < nb_ru; inst++) { - LOG_I(PHY, "Stopping RU %d processing threads\n", inst); - kill_NR_RU_proc(inst); - } -} - - -/* --------------------------------------------------------*/ -/* from here function to use configuration module */ -void RCconfig_RU(void) -{ - int i = 0, j = 0; - paramdef_t RUParams[] = RUPARAMS_DESC; - paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; - config_getlist( &RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL); - - if ( RUParamList.numelt > 0) { - RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); - RC.ru_mask=(1<idx = j; - RC.ru[j]->nr_frame_parms = (NR_DL_FRAME_PARMS *)malloc(sizeof(NR_DL_FRAME_PARMS)); - RC.ru[j]->frame_parms = (LTE_DL_FRAME_PARMS *)malloc(sizeof(LTE_DL_FRAME_PARMS)); - printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]); - RC.ru[j]->if_timing = synch_to_ext_device; - - if (RC.nb_nr_L1_inst >0) - RC.ru[j]->num_gNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt; - else - 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]]; - - if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { - RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); - } - - if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { - if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { - RC.ru[j]->openair0_cfg.clock_source = internal; - LOG_D(PHY, "RU clock source set as internal\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { - RC.ru[j]->openair0_cfg.clock_source = external; - LOG_D(PHY, "RU clock source set as external\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { - RC.ru[j]->openair0_cfg.clock_source = gpsdo; - LOG_D(PHY, "RU clock source set as gpsdo\n"); - } else { - LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); - } - } - else { - RC.ru[j]->openair0_cfg.clock_source = unset; - } - - if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { - if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { - RC.ru[j]->openair0_cfg.time_source = internal; - LOG_D(PHY, "RU time source set as internal\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { - RC.ru[j]->openair0_cfg.time_source = external; - LOG_D(PHY, "RU time source set as external\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { - RC.ru[j]->openair0_cfg.time_source = gpsdo; - LOG_D(PHY, "RU time source set as gpsdo\n"); - } else { - LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); - } - } - else { - RC.ru[j]->openair0_cfg.time_source = unset; - } - - if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { - if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = gNodeB_3GPP; - printf("Setting function for RU %d to gNodeB_3GPP\n",j); - } else { - RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); - - if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j); - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j); - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j); - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = NGFI_RRU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j); - } - } - - RC.ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; - RC.ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); - RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; - - for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; - } //strcmp(local_rf, "yes") == 0 - else { - printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); - RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); - - if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { - RC.ru[j]->if_south = REMOTE_IF4p5; - RC.ru[j]->function = NGFI_RAU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { - RC.ru[j]->if_south = REMOTE_IF4p5; - RC.ru[j]->function = NGFI_RAU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - } - } /* strcmp(local_rf, "yes") != 0 */ - - RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); - RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); - RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); - RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); - RC.ru[j]->if_frequency = *(RUParamList.paramarray[j][RU_IF_FREQUENCY].u64ptr); - RC.ru[j]->if_freq_offset = *(RUParamList.paramarray[j][RU_IF_FREQ_OFFSET].iptr); - - if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) { - RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt; - for (i=0; inum_gNB; i++) { - RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t)); - for (int b=0; bnb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b]; - } - } - }// j=0..num_rus - } else { - RC.nb_RU = 0; - } // setting != NULL - - return; -} - diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index a2d2a2863e..98757b09d0 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -73,6 +73,7 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; extern int sync_var; +char uecap_xer_in; extern void init_eNB_afterRU(void); extern void init_UE_stub(int nb_inst,int,int); @@ -1242,7 +1243,6 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); int SFN=sfn+2; //if(!&dl_tti_pdu->pdcch_pdu) - printf("interleaversize = %d, coreset_type = %d. \n",dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize,dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15.CoreSetType); handle_nfapi_nr_pdcch_pdu(gNB, SFN, slot, &dl_tti_pdu->pdcch_pdu); //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); @@ -1474,7 +1474,6 @@ int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, switch (ul_tti_pdu_list[i].pdu_type) { case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); - //curr_sfn = curr_sfn + 3; //Gokul nr_fill_ulsch(gNB,curr_sfn, curr_slot, &ul_tti_pdu_list[i].pusch_pdu); break; case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: @@ -2201,7 +2200,7 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add pnf.phys[0].udp.tx_port = vnf_p7_port; strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr); strcpy(pnf.phys[0].local_addr, pnf_ip_addr); - printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%u rx:%u]\n", + printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%d rx:%d]\n", __FUNCTION__,config->vnf_ip_addr, config->vnf_p5_port, pnf.phys[0].local_addr, pnf.phys[0].udp.tx_addr, pnf.phys[0].udp.tx_port, @@ -2252,7 +2251,7 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, pnf.phys[0].udp.tx_port = vnf_p7_port; strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr); strcpy(pnf.phys[0].local_addr, pnf_ip_addr); - printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%u rx:%u]\n", + printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%d rx:%d]\n", __FUNCTION__, config->vnf_ip_addr, config->vnf_p5_port, pnf.phys[0].local_addr, @@ -2405,3 +2404,36 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //free(ind.rx_indication_body.rx_pdu_list); return retval; } + +//NR UPLINK INDICATION + +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; + return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION; + return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION; + return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION; + return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind); +} + +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION; + return nfapi_pnf_p7_nr_rach_ind(p7_config_g, ind); +} + diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 61d4847eba..b3ab7cbdbc 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -21,7 +21,6 @@ #if !defined(NFAPI_PNF_H__) #define NFAPI_PNF_H__ -extern nfapi_ue_release_request_body_t release_rntis; int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 7bbe51f3f0..12dda62eaf 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -250,7 +250,7 @@ void oai_create_gnb(void) { RC.gNB[0] = (PHY_VARS_gNB *) calloc(1, sizeof(PHY_VARS_gNB)); LOG_I(PHY,"[nr-gnb.c] gNB structure RC.gNB[%d] allocated @ %p\n",0,RC.gNB[0]); } - + PHY_VARS_gNB *gNB = RC.gNB[0]; RC.nb_nr_CC = (int *)malloc(sizeof(int)); // TODO: find a better function to place this in diff --git a/nfapi/open-nFAPI/common/src/debug.c b/nfapi/open-nFAPI/common/src/debug.c index f53be43223..a45d41d7d7 100644 --- a/nfapi/open-nFAPI/common/src/debug.c +++ b/nfapi/open-nFAPI/common/src/debug.c @@ -1,76 +1,76 @@ -/* - * Copyright 2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * 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. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MAX_MSG_LENGTH 2096 -#define TRACE_HEADER_LENGTH 44 - -void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...); - -// initialize the trace function to 0 -void (*nfapi_trace_g)(nfapi_trace_level_t level, const char* format, ...) = &nfapi_trace_dbg; - -nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_INFO; -//nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_WARN; - -void nfapi_set_trace_level(nfapi_trace_level_t new_level) -{ - nfapi_trace_level_g = new_level; -} - -void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...) -{ - char trace_buff[MAX_MSG_LENGTH + TRACE_HEADER_LENGTH]; - uint32_t num_chars; - va_list p_args; - struct timeval tv; - pthread_t tid = pthread_self(); - - (void)gettimeofday(&tv, NULL); - - num_chars = (uint32_t)snprintf(trace_buff, TRACE_HEADER_LENGTH, "%04u.%06u: 0x%02x: %10u: ", ((uint32_t)tv.tv_sec) & 0x1FFF, (uint32_t)tv.tv_usec, (uint32_t)level, (uint32_t)tid); - - if (num_chars > TRACE_HEADER_LENGTH) - { - printf("trace_dbg: Error, num_chars is too large: %u", num_chars); - return; - } - - va_start(p_args, format); - if ((num_chars = (uint32_t)vsnprintf(&trace_buff[num_chars], MAX_MSG_LENGTH, format, p_args))) - { - if (level <= NFAPI_TRACE_WARN) - { - printf("%s", trace_buff); - } - printf("%s", trace_buff); - } - va_end(p_args); -} +/* + * Copyright 2017 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_MSG_LENGTH 2096 +#define TRACE_HEADER_LENGTH 44 + +void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...); + +// initialize the trace function to 0 +void (*nfapi_trace_g)(nfapi_trace_level_t level, const char* format, ...) = &nfapi_trace_dbg; + +nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_INFO; +//nfapi_trace_level_t nfapi_trace_level_g = NFAPI_TRACE_WARN; + +void nfapi_set_trace_level(nfapi_trace_level_t new_level) +{ + nfapi_trace_level_g = new_level; +} + +void nfapi_trace_dbg(nfapi_trace_level_t level, const char *format, ...) +{ + char trace_buff[MAX_MSG_LENGTH + TRACE_HEADER_LENGTH]; + uint32_t num_chars; + va_list p_args; + struct timeval tv; + pthread_t tid = pthread_self(); + + (void)gettimeofday(&tv, NULL); + + num_chars = (uint32_t)snprintf(trace_buff, TRACE_HEADER_LENGTH, "%04u.%06u: 0x%02x: %10u: ", ((uint32_t)tv.tv_sec) & 0x1FFF, (uint32_t)tv.tv_usec, (uint32_t)level, (uint32_t)tid); + + if (num_chars > TRACE_HEADER_LENGTH) + { + printf("trace_dbg: Error, num_chars is too large: %d", num_chars); + return; + } + + va_start(p_args, format); + if ((num_chars = (uint32_t)vsnprintf(&trace_buff[num_chars], MAX_MSG_LENGTH, format, p_args))) + { + if (level <= NFAPI_TRACE_WARN) + { + printf("%s", trace_buff); + } + printf("%s", trace_buff); + } + va_end(p_args); +} diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 0436f92a8d..9df9be4cbd 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -972,7 +972,7 @@ typedef struct typedef struct { - int ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) + uint32_t ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) uint8_t bch_payload;//Defines option selected for generation of BCH payload, see Table 3-13 (v0.0.011 Value: 0: MAC generates the full PBCH payload 1: PHY generates the timing PBCH bits 2: PHY generates the full PBCH payload uint8_t scs_common;//subcarrierSpacing for common, used for initial access and broadcast message. [38.211 sec 4.2] Value:0->3 @@ -1058,6 +1058,12 @@ typedef struct { fapi_nr_tdd_table_t tdd_table; fapi_nr_prach_config_t prach_config; + fapi_nr_dl_bwp_common_config_t dl_bwp_common; + fapi_nr_dl_bwp_dedicated_config_t dl_bwp_dedicated; + + fapi_nr_ul_bwp_common_config_t ul_bwp_common; + fapi_nr_ul_bwp_dedicated_config_t ul_bwp_dedicated; + } fapi_nr_config_request_t; #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index bcb0a94ca8..aa3324e17d 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -1474,7 +1474,7 @@ typedef enum { //section 3.4.7 rx_data_indication -//table 3-61 +///table 3-61 typedef struct { @@ -1492,10 +1492,11 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_of_pdus; - nfapi_nr_rx_data_pdu_t* pdu_list; + nfapi_nr_rx_data_pdu_t *pdu_list; } nfapi_nr_rx_data_indication_t; @@ -1518,6 +1519,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t number_crcs; @@ -1655,6 +1657,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint16_t num_ucis; @@ -1691,6 +1694,7 @@ typedef struct typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; @@ -1723,6 +1727,7 @@ typedef struct{ typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; uint16_t slot; uint8_t number_of_pdus; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 8f6a736a14..4097217f99 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -1,8271 +1,8803 @@ -/* - * Copyright 2017 Cisco Systems, Inc. - * - * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - * - * 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. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "nfapi_nr_interface_scf.h" - -extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, void* user_data); -extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedMsg, void* user_data); - -uint32_t nfapi_calculate_checksum(uint8_t* buffer, uint16_t len) -{ - uint32_t chksum = 0; - // calcaulte upto the checksum - chksum = crc32(chksum, buffer, 8); - - // skip the checksum - uint8_t zeros[4] = {0, 0, 0, 0}; - chksum = crc32(chksum, zeros, 4); - - // continu with the rest of the mesage - chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH); - - // return the inverse - return ~(chksum); -} - -int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len) -{ - uint32_t checksum = nfapi_calculate_checksum(buffer, len); - - uint8_t* p_write = &buffer[8]; - return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); -} - -int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp) -{ - uint8_t* p_write = &buffer[12]; - return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); -} - -uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len) -{ - return nfapi_calculate_checksum(buffer, len); -} - -void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config) -{ - if(size == 0) - return 0; - - void* buffer_p = NULL; - if(config && config->allocate) - { - buffer_p = (config->allocate)(size); - if(buffer_p != NULL){ - memset(buffer_p,0,size); - } - return buffer_p; - } - else - { - buffer_p = calloc(1, size); - return buffer_p; - } -} - -void nfapi_p7_deallocate(void* ptr, nfapi_p7_codec_config_t* config) -{ - if(ptr == NULL) - return; - - if(config && config->deallocate) - { - return (config->deallocate)(ptr); - } - else - { - return free(ptr); - } -} -// Pack routines - - -static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel8_t* value = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format); - - return ( push8(value->dci_format, ppWritePackedMsg, end) && - push8(value->cce_idx, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs_1, ppWritePackedMsg, end) && - push8(value->redundancy_version_1, ppWritePackedMsg, end) && - push8(value->new_data_indicator_1, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->mcs_2, ppWritePackedMsg, end) && - push8(value->redundancy_version_2, ppWritePackedMsg, end) && - push8(value->new_data_indicator_2, ppWritePackedMsg, end) && - push8(value->harq_process, ppWritePackedMsg, end) && - push8(value->tpmi, ppWritePackedMsg, end) && - push8(value->pmi, ppWritePackedMsg, end) && - push8(value->precoding_information, ppWritePackedMsg, end) && - push8(value->tpc, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end) && - push8(value->transport_block_size_index, ppWritePackedMsg, end) && - push8(value->downlink_power_offset, ppWritePackedMsg, end) && - push8(value->allocate_prach_flag, ppWritePackedMsg, end) && - push8(value->preamble_index, ppWritePackedMsg, end) && - push8(value->prach_mask_index, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel9_t* value = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; - - return( push8(value->mcch_flag, ppWritePackedMsg, end) && - push8(value->mcch_change_notification, ppWritePackedMsg, end) && - push8(value->scrambling_identity, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel10_t* value = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; - - return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && - push8(value->carrier_indicator, ppWritePackedMsg, end) && - push8(value->srs_flag, ppWritePackedMsg, end) && - push8(value->srs_request, ppWritePackedMsg, end) && - push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(value->n_dl_rb, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel11_t* value = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; - - return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel12_t* value = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; - - return ( push8(value->primary_cell_type, ppWritePackedMsg, end) && - push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) && - push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) && - pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end)); -} - -static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->num_antennas, ppWritePackedMsg, end))) - return 0; - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); - - if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) && - push8(subband_info->scheduled_ues, ppWritePackedMsg, end))) - return 0; - - - uint8_t antenna_idx = 0; - uint8_t scheduled_ue_idx = 0; - - for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) - { - for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) - { - if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end)) - return 0; - } - } - - } - - - return 1; - -} - - -static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; - - return( - push16(value->bwp_size, ppWritePackedMsg, end) && - push16(value->bwp_start, ppWritePackedMsg, end) && - - push8(value->subcarrier_spacing, ppWritePackedMsg, end) && - push8(value->cyclic_prefix, ppWritePackedMsg, end) && - - push16(value->start_rb, ppWritePackedMsg, end) && - push16(value->nr_of_rbs, ppWritePackedMsg, end) && - - push8(value->csi_type, ppWritePackedMsg, end) && - push8(value->row, ppWritePackedMsg, end) && - - push16(value->freq_domain, ppWritePackedMsg, end) && - push8(value->symb_l0, ppWritePackedMsg, end) && - - push8(value->symb_l1, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - - push8(value->freq_density, ppWritePackedMsg, end) && - push16(value->scramb_id, ppWritePackedMsg, end) && - - push8(value->power_control_offset, ppWritePackedMsg, end) && - push8(value->power_control_offset_ss, ppWritePackedMsg, end) - ); - -} - - -static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && - - push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && - - push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) - return 0; - - } - - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->BWPSize, ppWritePackedMsg, end) && - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->CceRegMappingType, ppWritePackedMsg, end) && - - push8(value->RegBundleSize, ppWritePackedMsg, end) && - push8(value->InterleaverSize, ppWritePackedMsg, end) && - push8(value->CoreSetType, ppWritePackedMsg, end) && - push16(value->ShiftIndex, ppWritePackedMsg, end) && - - push8(value->precoderGranularity, ppWritePackedMsg, end) && - push16(value->numDlDci, ppWritePackedMsg, end)); - -} - - -static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; - - // TODO: resolve the packaging of array (currently sending a single element) - return( - push16(value->pduBitmap, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->pduIndex, ppWritePackedMsg, end) && - push16(value->BWPSize, ppWritePackedMsg, end) && - - push16(value->BWPStart, ppWritePackedMsg, end) && - push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->CyclicPrefix, ppWritePackedMsg, end) && - push8(value->NrOfCodewords, ppWritePackedMsg, end) && - - pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && - pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && - - pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && - pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && - push16(value->dataScramblingId, ppWritePackedMsg, end) && - push8(value->nrOfLayers, ppWritePackedMsg, end) && - - push8(value->transmissionScheme, ppWritePackedMsg, end) && - push8(value->refPoint, ppWritePackedMsg, end) && - push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && - push8(value->dmrsConfigType, ppWritePackedMsg, end) && - - push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && - push8(value->SCID, ppWritePackedMsg, end) && - push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && - push16(value->dmrsPorts, ppWritePackedMsg, end) && - - push8(value->resourceAlloc, ppWritePackedMsg, end) && - push16(value->rbStart, ppWritePackedMsg, end) && - push16(value->rbSize, ppWritePackedMsg, end) && - - push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && - push8(value->StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->NrOfSymbols, ppWritePackedMsg, end) && - push8(value->PTRSPortIndex, ppWritePackedMsg, end) && - - push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && - push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && - push8(value->PTRSReOffset, ppWritePackedMsg, end) - ); - -} - - -static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - printf("Packing ssb. \n"); - nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; - - return( - push16(value->PhysCellId, ppWritePackedMsg, end) && - push8(value->BetaPss, ppWritePackedMsg, end) && - push8(value->SsbBlockIndex, ppWritePackedMsg, end) && - push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && - push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && - push8(value->bchPayloadFlag, ppWritePackedMsg, end) && - push32(value->bchPayload, ppWritePackedMsg, end) - // TODO: pack precoding_and_beamforming too - ); - -} - - -static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel13_t* value = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; - - return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && - push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end) && - push8(value->codebook_size_determination, ppWritePackedMsg, end) && - push8(value->drms_table_flag, ppWritePackedMsg, end) && - push8(value->tpm_struct_flag, ppWritePackedMsg, end) && - (value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1)); -} - -static uint8_t pack_dl_config_bch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_bch_pdu_rel8_t* value = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__); - - return( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_mch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_mch_pdu_rel8_t* value = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->mbsfn_area_id, ppWritePackedMsg, end)); -} - -static uint8_t pack_bf_vector_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_bf_vector_t* bf = (nfapi_bf_vector_t*)elem; - - return ( push8(bf->subband_index, ppWritePackedMsg, end) && - push8(bf->num_antennas, ppWritePackedMsg, end) && - pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end)); - - -} -static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel8_t* value = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->transport_blocks, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->transmission_scheme, ppWritePackedMsg, end) && - push8(value->number_of_layers, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->ue_category_capacity, ppWritePackedMsg, end) && - push8(value->pa, ppWritePackedMsg, end) && - push8(value->delta_power_offset_index, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end) && - push8(value->nprb, ppWritePackedMsg, end) && - push8(value->transmission_mode, ppWritePackedMsg, end) && - push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) && - push8(value->num_bf_vector, ppWritePackedMsg, end) && - packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info)); - -} -static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel9_t* value = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; - return ( push8(value->nscid, ppWritePackedMsg, end) ); -} -static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel10_t* value = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; - - return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) && - push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && - push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && - pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && - push8(value->pdsch_start, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel11_t* value = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; - - return( push8(value->drms_config_flag, ppWritePackedMsg, end) && - push16(value->drms_scrambling, ppWritePackedMsg, end) && - push8(value->csi_config_flag, ppWritePackedMsg, end) && - push16(value->csi_scrambling, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) && - push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel12_t* value = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; - - return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) && - push8(value->maxlayers, ppWritePackedMsg, end) && - push8(value->n_dl_harq, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel13_t* value = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; - - return( push8(value->dwpts_symbols, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end) && - push8(value->ue_type, ppWritePackedMsg, end) && - push8(value->pdsch_payload_type, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && - push8(value->drms_table_flag, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_pch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel8_t* value = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; - - return( push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->p_rnti, ppWritePackedMsg, end) && - push8(value->resource_allocation_type, ppWritePackedMsg, end) && - push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && - push32(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->number_of_transport_blocks, ppWritePackedMsg, end) && - push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && - push8(value->transmission_scheme, ppWritePackedMsg, end) && - push8(value->number_of_layers, ppWritePackedMsg, end) && - push8(value->codebook_index, ppWritePackedMsg, end) && - push8(value->ue_category_capacity, ppWritePackedMsg, end) && - push8(value->pa, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->nprb, ppWritePackedMsg, end) && - push8(value->ngap, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_pch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel13_t* value = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; - - return ( push8(value->ue_mode, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_prs_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_prs_pdu_rel9_t* value = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; - - return( push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->prs_bandwidth, ppWritePackedMsg, end) && - push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) && - push8(value->prs_muting, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel10_t* value = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; - - return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && - push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) && - pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel13_t* value = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; - - if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) && - push8(value->cdm_type, ppWritePackedMsg, end) && - push8(value->num_bf_vector, ppWritePackedMsg, end))) - { - return 0; - } - - uint16_t i; - for(i = 0; i < value->num_bf_vector; ++i) - { - if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) && - pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} -static uint8_t pack_bf_vector(nfapi_bf_vector_t* vector, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(vector->subband_index, ppWritePackedMsg, end) && - push8(vector->num_antennas, ppWritePackedMsg, end) && - pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel11_t* value = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; - - return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) && - push16(value->epdcch_id, ppWritePackedMsg, end) && - push8(value->epdcch_start_symbol, ppWritePackedMsg, end) && - push8(value->epdcch_num_prb, ppWritePackedMsg, end) && - pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) && - pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel13_t* value = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; - - return (push8(value->dwpts_symbols, ppWritePackedMsg, end) && - push8(value->initial_lbt_sf, ppWritePackedMsg, end)); -} -static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_mpdcch_pdu_rel13_t* value = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; - - return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) && - push8(value->number_of_prb_pairs, ppWritePackedMsg, end) && - push8(value->resource_block_assignment, ppWritePackedMsg, end) && - push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->ecce_index, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->ce_mode, ppWritePackedMsg, end) && - push16(value->drms_scrambling_init, ppWritePackedMsg, end) && - push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push8(value->dci_format, ppWritePackedMsg, end) && - push16(value->resource_block_coding, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) && - push8(value->redundancy_version, ppWritePackedMsg, end) && - push8(value->new_data_indicator, ppWritePackedMsg, end) && - push8(value->harq_process, ppWritePackedMsg, end) && - push8(value->tpmi_length, ppWritePackedMsg, end) && - push8(value->tpmi, ppWritePackedMsg, end) && - push8(value->pmi_flag, ppWritePackedMsg, end) && - push8(value->pmi, ppWritePackedMsg, end) && - push8(value->harq_resource_offset, ppWritePackedMsg, end) && - push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push8(value->tpc, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) && - push8(value->downlink_assignment_index, ppWritePackedMsg, end) && - push8(value->allocate_prach_flag, ppWritePackedMsg, end) && - push8(value->preamble_index, ppWritePackedMsg, end) && - push8(value->prach_mask_index, ppWritePackedMsg, end) && - push8(value->starting_ce_level, ppWritePackedMsg, end) && - push8(value->srs_request, ppWritePackedMsg, end) && - push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) && - push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) && - push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) && - push8(value->direct_indication, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) && - pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end)); -} - - -static uint8_t pack_dl_config_nbch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_nbch_pdu_rel13_t* value = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push16(value->transmission_power, ppWritePackedMsg, end) && - push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end)); -} - - -static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_npdcch_pdu_rel13_t* value = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push8(value->ncce_index, ppWritePackedMsg, end) && - push8(value->aggregation_level, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && - push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && - push8(value->dci_format, ppWritePackedMsg, end) && - push8(value->scheduling_delay, ppWritePackedMsg, end) && - push8(value->resource_assignment, ppWritePackedMsg, end) && - push8(value->repetition_number, ppWritePackedMsg, end) && - push8(value->mcs, ppWritePackedMsg, end) && - push8(value->new_data_indicator, ppWritePackedMsg, end) && - push8(value->harq_ack_resource, ppWritePackedMsg, end) && - push8(value->npdcch_order_indication, ppWritePackedMsg, end) && - push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) && - push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) && - push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) && - push8(value->direct_indication, ppWritePackedMsg, end) && - push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push8(value->total_dci_length_including_padding, ppWritePackedMsg, end)); -} - -static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_ndlsch_pdu_rel13_t* value = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; - - return (push16(value->length, ppWritePackedMsg, end) && - push16(value->pdu_index, ppWritePackedMsg, end) && - push8(value->start_symbol, ppWritePackedMsg, end) && - push8(value->rnti_type, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) && - push16(value->resource_assignment, ppWritePackedMsg, end) && - push16(value->repetition_number, ppWritePackedMsg, end) && - push8(value->modulation, ppWritePackedMsg, end) && - push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) && - push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && - push16(value->sf_idx, ppWritePackedMsg, end) && - push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); -} - - -static uint8_t pack_dl_tti_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)tlv; - - if(!(push16(value->PDUSize, ppWritePackedMsg, end) && - push16(value->PDUType, ppWritePackedMsg, end) )) - return 0; - - - // first match the pdu type, then call the respective function - switch(value->PDUType) - { - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - { - if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - { - if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - { - if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - { - if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; - } - - return 1; -} - -static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; - - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich); - - if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) && - push8(value->number_dci, ppWritePackedMsg, end) && - push16(value->number_pdu, ppWritePackedMsg, end) && - push8(value->number_pdsch_rnti, ppWritePackedMsg, end) && - push16(value->transmission_power_pcfich, ppWritePackedMsg, end))) - { - return 0; - } - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_pdu; - for(; i < total_number_of_pdus; ++i) - { - nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__); - - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value))) - { - return 0; - } - } - break; - case NFAPI_DL_CONFIG_BCH_PDU_TYPE: - { - //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__); - - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_MCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_PCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_PRS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) && - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) & - pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - - -static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; - - if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nGroup , ppWritePackedMsg, end) && - push8(pNfapiMsg->dl_tti_request_body.nPDUs , ppWritePackedMsg, end) && - pusharray8(pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) - return 0; - - int arr[12]; - for(int i=0;idl_tti_request_body.nGroup;i++) - { - for(int j=0;jdl_tti_request_body.nUe[i];j++) - { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - if(!(pusharrays32(arr,12,pNfapiMsg->dl_tti_request_body.nUe[i],ppWritePackedMsg, end))) - return 0; - } - - for(int i=0;idl_tti_request_body.nPDUs;i++) - { - if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) - return 0; - } - -return 1; -} - - -static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; - - //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) && - //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - { - uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value); - uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - - if (!x || !y || !z) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z); - } - - return x && y && z; - } -} - - - - -static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t * end) -{ - nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; - - return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; - - return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && - push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; - - return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; - - return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && - push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); -} - -//Pack fns for ul_tti PDUS - - -static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t* prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && - push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && - push8(prach_pdu->prach_format, ppWritePackedMsg, end) && - push8(prach_pdu->num_ra, ppWritePackedMsg, end) && - push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && - push16(prach_pdu->num_cs, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); - -} - -static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t* pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(pucch_pdu->rnti, ppWritePackedMsg, end) && - push32(pucch_pdu->handle, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(pucch_pdu->format_type, ppWritePackedMsg, end) && - push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && - push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && - push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && - push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && - push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && - push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && - push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && - push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && - push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && - push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && - push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && - push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && - push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - ); - -} - - -static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t* pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - - if (!( - push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && - push16(pusch_pdu->rnti, ppWritePackedMsg, end) && - push32(pusch_pdu->handle, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && - push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && - push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && - push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && - push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && - push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && - push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && - push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && - push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && - push8(pusch_pdu->scid, ppWritePackedMsg, end) && - push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && - push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && - push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && - push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && - push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && - push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && - push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && - push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && - push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && - push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) - // TODO: ignoring beamforming tlv for now - )) - return 0; - - - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map){ - case PUSCH_PDU_BITMAP_PUSCH_DATA: - { - // pack optional TLVs - return( - push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && - push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && - pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: - { - return( - push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: - { - return( - push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && - push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && - push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: - { - return( - push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && - push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && - push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) - ); - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); - } - } - - return 1; -} - -static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t* srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return( - push16(srs_pdu->rnti, ppWritePackedMsg, end) && - push32(srs_pdu->handle, ppWritePackedMsg, end) && - push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && - push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && - push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && - push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && - push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && - push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && - push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && - push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && - push8(srs_pdu->config_index, ppWritePackedMsg, end) && - push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && - push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && - push8(srs_pdu->comb_size, ppWritePackedMsg, end) && - push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && - push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_shift, ppWritePackedMsg, end) && - push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && - push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && - push8(srs_pdu->resource_type, ppWritePackedMsg, end) && - push16(srs_pdu->t_srs, ppWritePackedMsg, end) && - push16(srs_pdu->t_offset, ppWritePackedMsg, end) - - // TODO: ignoring beamforming tlv for now - ); - -} - -static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu* ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value)); -} - -static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; - - return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; - - if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end))) - { - return 0; - } - - switch(cqi_ri_info_rel9->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) && - push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end))) - { - return 0; - } - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t i; - for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0) - return 0; - - uint8_t j; - for(j = 0; j < 8; ++j) - { - if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0) - return 0; - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); - } - break; - }; - - return 1; -} - -static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; - - switch(cqi_ri_info_rel13->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0) - return 0; - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - // No parameters - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type ); - } - break; - }; - - return 1; -} - -static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information* cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value)); - -} - -static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; - - return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) && - push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters* init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, &pack_ul_config_request_init_tx_params_rel8_value); -} - -static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; - - return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) && - push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; - - return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && - push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value)); -} - -static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; - - return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) && - push16(ue_info_rel8->rnti, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; - - return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && - push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; - - return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) && - push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) && - push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && - push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information* ue_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value)); -} - -static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; - - return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) && - push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) && - push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; - - return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) && - push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; - - return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) && - push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) && - push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) && - push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; - - return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) && - push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; - - return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && - push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) && - push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) && - push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) && - push8(harq_info_rel13->n_srs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value)); - -} - -static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; - - return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) && - push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; - - return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) && - push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); -} -static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; - - return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) && - push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) && - push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) && - push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) && - push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) && - push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information* cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value)); - -} - -static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; - return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end); -} -static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; - - return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) && - push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information* sr_info, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value)); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; - - return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->size, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; - return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end); -} - -static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; - - return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; - - return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; - - return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) && - push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && - push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && - push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && - pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, &pack_ul_config_request_nb_harq_rel13_value)); -} -static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; - - return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) && - push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) && - push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); - -} - - - -static uint8_t pack_ul_tti_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_tti_request_number_of_pdus_t* value = (nfapi_nr_ul_tti_request_number_of_pdus_t*)tlv; - - if(!(push16(value->pdu_size, ppWritePackedMsg, end) && - push16(value->pdu_type, ppWritePackedMsg, end) )) - return 0; - - - // first match the pdu type, then call the respective function - switch(value->pdu_type) - { - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - { - if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - { - if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - { - if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - { - if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); - } - break; - } - - return 1; -} - -static uint8_t pack_ul_tti_groups_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_tti_request_number_of_groups_t* value = (nfapi_nr_ul_tti_request_number_of_groups_t*)tlv; - - if(!push8(value->n_ue, ppWritePackedMsg, end)) - return 0; - for(int i=0; in_ue;i++) - { - if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) - return 0; - } - return 1; -} - -static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; - - if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) && - push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) && - push8(value->srs_present, ppWritePackedMsg, end))) - return 0; - - uint16_t i = 0; - for(i = 0; i < value->number_of_pdus; ++i) - { - nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - { - if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end)) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && - pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) && - pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) && - pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_SRS_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: - { - if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - { - if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && - pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) && - pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) - return 0; - } - break; - case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value))) - return 0; - } - break; - case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - - } - return 1; -} - - -static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; - - if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && - push8(pNfapiMsg->n_pdus , ppWritePackedMsg, end) && - push8(pNfapiMsg->rach_present, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end) && - push8(pNfapiMsg->n_group, ppWritePackedMsg, end) )) - return 0; - - for(int i=0; in_pdus; i++) - { - if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) - return 0; - } - - for(int i=0; in_group; i++) - { - if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) - return 0; - - } - - return 1; -} - - -static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ; -} - -static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; - - return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) && - push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) && - push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; - - return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) && - push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; - - return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) && - push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) && - push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) && - push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) && - push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; - - return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && - push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) && - push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; - - return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) && - push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end)); -} - -static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; - - return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && - push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) && - push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) && - push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) && - pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end)); - -} - -static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; - - return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && - push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) && - push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end)); -} - - -static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; - - if(!(push16(value->sfnsf, ppWritePackedMsg, end) && - push8(value->number_of_dci, ppWritePackedMsg, end) && - push8(value->number_of_hi, ppWritePackedMsg, end))) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); - - if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_HI_DCI0_HI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value))) - return 0; - } - break; - case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: - { - if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value))) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - - } - - return 1; -} - -static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && - - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && - - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) - - return 0; - } - - return (push16(value->PDUType, ppWritePackedMsg, end) && - push16(value->PDUSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && - pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && - - push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && - push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && - push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); - -} - -static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; - - if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && - push8(pNfapiMsg->numPdus, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; inumPdus; i++) - { - if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) - return 0; - } - return 1; - - -} - - - -static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -//pack_tx_data_pdu_list_value -static uint8_t pack_tx_data_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nr_pdu_t* value = (nfapi_nr_pdu_t*)tlv; - - if(!(push32(value->num_TLV, ppWritePackedMsg, end) && - push16(value->PDU_index, ppWritePackedMsg, end) && - push16(value->PDU_length, ppWritePackedMsg, end) - )) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_tlvs = value->num_TLV; - for(; i < total_number_of_tlvs; ++i) - { - - if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && - push16(value->TLVs[i].tag, ppWritePackedMsg, end))) - return 0; - - switch(value->TLVs[i].tag) - { - case 0: - { - if(!pusharray32(value->TLVs[i].value.direct, 16384, value->TLVs[i].length, ppWritePackedMsg, end)) - return 0; - break; - - } - - case 1: - { - if(!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length , value->TLVs[i].length, ppWritePackedMsg, end)) - return 0; - break; - - } - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); - break; - } - - } - } - return 1; -} - -static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_tx_request_body_t* value = (nfapi_tx_request_body_t*)tlv; - - if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_tx_request_pdu_t* pdu = &(value->tx_pdu_list[i]); - - if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) && - push16(pdu->pdu_index, ppWritePackedMsg, end))) - return 0; - - uint8_t j; - for(j = 0; j < pdu->num_segments; ++j) - { - // Use -1 as it is unbounded - // DJP - does not handle -1 - // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) - int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); - - if (pdu->segments[j].segment_length == 3) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, - pdu->segments[j].segment_data[0], - pdu->segments[j].segment_data[1], - pdu->segments[j].segment_data[2] - ); - } - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret); - - if (push_ret == 0) - { - return 0; - } - } - } - - return 1; -} - -static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; - - if (!( - push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && - push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && - push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) - )) - return 0; - - for(int i=0; iNumber_of_PDUs; i++) - { - if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) - return 0; - } - - return 1; -} - -static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; - - int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z); - - return x && y && z; -} - -static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv; - if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){ - return 0; - } - - uint8_t j; - uint16_t num = value->number_of_TLVs; - for(j = 0; j < num; ++j){ - if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){ - return 0; - } - } - return 1; -} - -static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; - int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return x && y && z; -} - -static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - - int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return x && z; -} - -static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push16(value->rnti, ppWritePackedMsg, end) ); -} - -static uint8_t unpack_rx_ue_information_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; - - return ( pull32(ppReadPackedMsg, &value->handle, end) && - pull16(ppReadPackedMsg, &value->rnti, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) && - push8(data->value_1, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) && - push8(data->value_1, ppWritePackedMsg, end) && - push8(data->value_2, ppWritePackedMsg, end) && - push8(data->value_3, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) ); -} - -static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - return ( push8(data->value_0, ppWritePackedMsg, end) ); -} - -static uint8_t pack_harq_indication_tdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel8_t* harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t*)tlv; - - if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) && - push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t result = 0; - switch(harq_indication_tdd_rel8->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = 1; - break; - default: - // err.... - break; - } - - return result; - -} - -static uint8_t pack_harq_indication_tdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel9_t* harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t*)tlv; - - if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) && - push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t idx; - for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - - switch(harq_indication_tdd_rel9->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end); - break; - default: - // err.... - break; - } - - if(result == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_harq_indication_tdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel13_t* harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t*)tlv; - - if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) && - push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end))) - return 0; - - uint8_t idx; - for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(harq_indication_tdd_rel13->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: - result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end); - break; - default: - // err.... - break; - } - - if(result == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_harq_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel8_t* harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t*)tlv; - - return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) && - push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel9_t* harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t*)tlv; - - return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) && - push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) && - pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)); -} - -static uint8_t pack_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel13_t* harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t*)tlv; - - return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) && - push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) && - pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)); -} - -static uint8_t pack_ul_cqi_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; - - return ( push8(value->ul_cqi, ppWritePackedMsg, end) && - push8(value->channel, ppWritePackedMsg, end)); - -} - -static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; - - if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_harqs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) && - pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) && - pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_crc_indication_rel8_t* crc_indication_rel8 = (nfapi_crc_indication_rel8_t*)tlv; - - return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) ); -} - -static uint8_t pack_crc_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; - - if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_crcs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - return 1; -} - -static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} -static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; - - return ( push16(value->length, ppWritePackedMsg, end) && - push16(value->offset, ppWritePackedMsg, end) && - push8(value->ul_cqi, ppWritePackedMsg, end) && - push16(value->timing_advance, ppWritePackedMsg, end)); -} -static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; - - return ( push16(value->timing_advance_r9, ppWritePackedMsg, end)); -} - -static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; - - //printf("RX ULSCH BODY\n"); - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - // need to calculate the data offset's. - uint16_t i = 0; - uint16_t offset = 2; // taking into account the number_of_pdus - uint16_t total_number_of_pdus = value->number_of_pdus; - //printf("ULSCH:pdus:%d\n", total_number_of_pdus); - - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) - { - //printf("NFAPI_RX_UE_INFORMATION_TAG\n"); - offset += 4 + 6; - } - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - //printf("NFAPI_RX_INDICATION_REL8_TAG\n"); - offset += 4 + 7; - } - - if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG) - { - //printf("NFAPI_RX_INDICATION_REL9_TAG\n"); - offset += 4 + 2; - } - } - - // Now update the structure to include the offset - for(i =0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - if(pdu->rx_indication_rel8.offset == 1) - { - pdu->rx_indication_rel8.offset = offset; - offset += pdu->rx_indication_rel8.length; - } - } - } - - // Write out the pdu - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) && - pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value))) - return 0; - } - - // Write out the pdu data - for(i = 0; i < total_number_of_pdus; ++i) - { - uint16_t length = 0; - nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); - - if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - length = pdu->rx_indication_rel8.length; - } - - if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0) - return 0; - } - return 1; -} - - -static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_preamble_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel8_t* preamble_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; - - return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) && - push8(preamble_rel8->preamble, ppWritePackedMsg, end) && - push16(preamble_rel8->timing_advance, ppWritePackedMsg, end)); -} -static uint8_t pack_preamble_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel9_t* preamble_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; - - return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) ); -} -static uint8_t pack_preamble_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel13_t* preamble_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; - - return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) ); -} - -static uint8_t pack_rach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; - - if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_preambles; - for(; i < total_number_of_pdus; ++i) - { - nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) && - pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) && - pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel8_t* srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; - - return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) && - push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && - push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) && - pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end)); -} - -static uint8_t pack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel9_t* srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; - - return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) ); -} - -static uint8_t pack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_ttd_rel10_t* srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; - - return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) ); - -} - -static uint8_t pack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel11_t* srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; - - return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ; -} - -static uint8_t pack_tdd_channel_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; - - if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) && - push8(value->number_of_subbands, ppWritePackedMsg, end) && - push8(value->num_atennas, ppWritePackedMsg, end))) - return 0; - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) && - pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end))) - return 0; - } - - return 1; -} - -static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t*)tlv; - - if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_ues; - for(; i < total_number_of_pdus; ++i) - { - nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) && - pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) && - pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) && - pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; - - if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_srs; - for(; i < total_number_of_pdus; ++i) - { - nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - return 1; -} - -static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; - - return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) && - push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) && - push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) && - push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) && - push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end)); -} - -static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; - - return ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) && - push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) && - push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && - pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) && - push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end)); -} - -static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; - - if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0) - return 0; - - // need to calculate the data offset's. This very bittle due the hardcoding - // of the sizes. can not use the sizeof as we have an array for the Rel9 - // info - uint16_t i = 0; - uint16_t offset = 2; // taking into account the number_of_cqis - uint16_t total_number_of_pdus = value->number_of_cqis; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - offset += 2; // for the instance length - - if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) - { - offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t) - } - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - offset += 4 + 8; - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported; - } - - if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG) - { - offset += 4 + 2; - } - } - - // Now update the structure to include the offset - for(i =0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - if(pdu->cqi_indication_rel8.data_offset == 1) - { - pdu->cqi_indication_rel8.data_offset = offset; - offset += pdu->cqi_indication_rel8.length; - } - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - if(pdu->cqi_indication_rel9.data_offset == 1) - { - pdu->cqi_indication_rel9.data_offset = offset; - offset += pdu->cqi_indication_rel9.length; - } - } - - } - - // Write out the cqi information - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end ,pack_rx_ue_information_value) && - pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) && - pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - - } - - // Write out the cqi raw data - for(i = 0; i < total_number_of_pdus; ++i) - { - uint16_t length = 0; - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - - if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - length = pdu->cqi_indication_rel8.length; - } - - if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - length = pdu->cqi_indication_rel9.length; - } - - if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0) - return 0; - } - - return 1; -} - -static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); - -} - -static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->mp_cca, ppWritePackedMsg, end) && - push32(value->n_cca, ppWritePackedMsg, end) && - push32(value->offset, ppWritePackedMsg, end) && - push32(value->lte_txop_sf, ppWritePackedMsg, end) && - push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) && - push32(value->lbt_mode, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->offset, ppWritePackedMsg, end) && - push16(value->sfn_sf_end, ppWritePackedMsg, end) && - push32(value->lbt_mode, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); - - if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0) - return 0; - } - break; - case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: - { - if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - -static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->result, ppWritePackedMsg, end) && - push32(value->lte_txop_symbols, ppWritePackedMsg, end) && - push32(value->initial_partial_sf, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; - - return ( push32(value->handle, ppWritePackedMsg, end) && - push32(value->result, ppWritePackedMsg, end)); -} - -static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_lbt_dl_config_indication_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; - - if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); - - if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) - return 0; - - // Put a 0 size in and then determine the size after the pdu - // has been writen and write the calculated size - uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; - pdu->pdu_size = 0; - - if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0) - return 0; - } - break; - case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: - { - if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0) - return 0; - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - - // add 1 for the pdu_type. The delta will include the pdu_size - pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); - push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); - } - - return 1; -} - -static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nb_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_fdd_rel13_t* nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; - - return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) ); -} - -static uint8_t pack_nb_harq_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; - - if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_harqs = value->number_of_harqs; - for(; i < total_number_of_harqs; ++i) - { - nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); - - uint8_t* instance_length_p = *ppWritePackedMsg; - if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - return 0; - - if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && - pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) && - pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - push16(instance_length, &instance_length_p, end); - } - - return 1; -} - - -static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nrach_indication_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_pdu_rel13_t* nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t*)tlv; - - return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) && - push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) && - push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) && - push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end)); -} - - -static uint8_t pack_nrach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; - - if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected; - for(; i < total_number_of_initial_scs_detected; ++i) - { - nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); - - //uint8_t* instance_length_p = *ppWritePackedMsg; - //if(!push16(pdu->instance_length, ppWritePackedMsg, end)) - // return 0; - - if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value))) - return 0; - - // calculate the instance length subtracting the size of the instance - // length feild - //uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; - //push16(instance_length, &instance_length_p, end); - } - - return 1; -} - -static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; - - return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && - pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; - - return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; - - return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; - - return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - push32(pNfapiMsg->t2, ppWritePackedMsg, end) && - push32(pNfapiMsg->t3, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; - - return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && - push32(pNfapiMsg->t2, ppWritePackedMsg, end) && - push32(pNfapiMsg->t3, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - - return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && - push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && - push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - -static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; - - return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && - push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) && - push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && - push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && - push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) && - pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) && - pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); -} - - - -// Main pack function - public - -int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *end = pPackedBuf + packedBufLen; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - /* - printf("\n P7 MESSAGE SENT: \n"); - for(int i=0; i< packedBufLen; i++){ - printf("%d", *(uint8_t *)(pMessageBuf + i)); - } - printf("\n"); - */ - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && - push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && - push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } - - if (pMessageHeader->message_id != NFAPI_TIMING_INFO) - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); - } - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_REQUEST: - result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p7_vendor_extension) - { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPackedBuf; - uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - if(!push16(packedMsgLen16, &pPackedLengthField, end)) - return -1; - - if(1) - { - //quick test - if(pMessageHeader->message_length != packedMsgLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); - } - } - - return (packedMsgLen); -} - -int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; - uint8_t *pWritePackedMessage = pPackedBuf; - uint8_t *pPackedLengthField = &pWritePackedMessage[4]; - uint8_t *end = pPackedBuf + packedBufLen; - - if (pMessageBuf == NULL || pPackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); - return -1; - } - /* - printf("\n P7 MESSAGE SENT: \n"); - for(int i=0; i< packedBufLen; i++){ - printf("%d", *(uint8_t *)(pMessageBuf + i)); - } - printf("\n"); - */ - // process the header - if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && - push16(pMessageHeader->message_id, &pWritePackedMessage, end) && - push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && - push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && - push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && - push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); - return -1; - } - - if (pMessageHeader->message_id != NFAPI_TIMING_INFO) - { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); - } - // look for the specific message - uint8_t result = 0; - switch (pMessageHeader->message_id) - { - case NFAPI_DL_CONFIG_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST\n", __FUNCTION__); - result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UL_CONFIG_REQUEST: - result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_TX_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); - result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - case NFAPI_HI_DCI0_REQUEST: - result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_REQUEST: - result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_HARQ_INDICATION: - result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_CRC_INDICATION: - result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_ULSCH_INDICATION: - //printf("RX ULSCH\n"); - result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RACH_INDICATION: - result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_SRS_INDICATION: - result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_SR_INDICATION: - result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_RX_CQI_INDICATION: - result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_LBT_DL_INDICATION: - result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NB_HARQ_INDICATION: - result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_NRACH_INDICATION: - result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_DL_NODE_SYNC: - result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UL_NODE_SYNC: - result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_TIMING_INFO: - result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config); - break; - - default: - { - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->pack_p7_vendor_extension) - { - result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - } - break; - } - - if(result == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); - return -1; - } - - // check for a valid message length - uintptr_t msgHead = (uintptr_t)pPackedBuf; - uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; - uint32_t packedMsgLen = msgEnd - msgHead; - uint16_t packedMsgLen16; - if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); - return -1; - } - else - { - packedMsgLen16 = (uint16_t)packedMsgLen; - } - - // Update the message length in the header - pMessageHeader->message_length = packedMsgLen16; - - if(!push16(packedMsgLen16, &pPackedLengthField, end)) - return -1; - - if(1) - { - //quick test - if(pMessageHeader->message_length != packedMsgLen) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); - } - } - - return (packedMsgLen); -} - -// Unpack routines -// NR: -static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; - - return( - pull16(ppReadPackedMsg, &value->bwp_size, end) && - pull16(ppReadPackedMsg, &value->bwp_start, end) && - - pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && - - pull16(ppReadPackedMsg, &value->start_rb, end) && - pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && - - pull8(ppReadPackedMsg, &value->csi_type, end) && - pull8(ppReadPackedMsg, &value->row, end) && - - pull16(ppReadPackedMsg, &value->freq_domain, end) && - pull8(ppReadPackedMsg, &value->symb_l0, end) && - - pull8(ppReadPackedMsg, &value->symb_l1, end) && - pull8(ppReadPackedMsg, &value->cdm_type, end) && - - pull8(ppReadPackedMsg, &value->freq_density, end) && - pull16(ppReadPackedMsg, &value->scramb_id, end) && - - pull8(ppReadPackedMsg, &value->power_control_offset, end) && - pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) - ); - -} - - -static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; - - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && - - pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && - - pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) - - return 0; - } - - // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->BWPSize, end) && - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && - - pull8(ppReadPackedMsg, &value->RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->CoreSetType, end) && - pull16(ppReadPackedMsg, &value->ShiftIndex, end) && - - pull8(ppReadPackedMsg, &value->precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->numDlDci, end)); - -} - - -static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; - - // TODO: resolve the packaging of array (currently sending a single element) - return( - pull16(ppReadPackedMsg, &value->pduBitmap, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull16(ppReadPackedMsg, &value->pduIndex, end) && - pull16(ppReadPackedMsg, &value->BWPSize, end) && - - pull16(ppReadPackedMsg, &value->BWPStart, end) && - pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && - pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && - - pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && - pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && - - pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && - pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && - pull16(ppReadPackedMsg, &value->dataScramblingId, end) && - pull8(ppReadPackedMsg, &value->nrOfLayers, end) && - - pull8(ppReadPackedMsg, &value->transmissionScheme, end) && - pull8(ppReadPackedMsg, &value->refPoint, end) && - pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && - pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && - - pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && - pull8(ppReadPackedMsg, &value->SCID, end) && - pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && - pull16(ppReadPackedMsg, &value->dmrsPorts, end) && - - pull8(ppReadPackedMsg, &value->resourceAlloc, end) && - pull16(ppReadPackedMsg, &value->rbStart, end) && - pull16(ppReadPackedMsg, &value->rbSize, end) && - - pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && - pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && - pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && - - pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && - pull8(ppReadPackedMsg, &value->PTRSReOffset, end) - ); - -} - - -static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - printf("ssb received and unpacked. \n"); - nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; - - return( - pull16(ppReadPackedMsg, &value->PhysCellId, end) && - pull8(ppReadPackedMsg, &value->BetaPss, end) && - pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && - pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && - pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && - pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && - pull32(ppReadPackedMsg, &value->bchPayload, end) - // TODO: pack precoding_and_beamforming too - ); - -} - - -// LTE: -static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel8_t* dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) && - pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) && - pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end)); - -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel9_t* dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel10_t* dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel11_t* dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end)); -} - -static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel12_t* dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) && - pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end)); -} - -static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end) -{ - if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && - pull8(ppReadPackedMsg, &value->number_of_subbands, end) && - pull8(ppReadPackedMsg, &value->num_antennas, end))) - return 0; - - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); - - if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) && - pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end))) - return 0; - - uint8_t antenna_idx = 0; - uint8_t scheduled_ue_idx = 0; - - for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) - { - for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) - { - if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end)) - return 0; - } - } - - } - - - return 1; - -} - - -static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dci_dl_pdu_rel13_t* dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; - - // If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been - // added - uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5; - dci_dl_pdu_rel13->tpm_struct_flag = 0; - - return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) && - pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && - ( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) && - ( (tpm_struct_flag_present == 1 && dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1)); - -} - -static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_bch_pdu_rel8_t* bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&bch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_mch_pdu_rel8_t* mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&mch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) && - pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end)); -} - -static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel8_t* dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; - - if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&dlsch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) && - pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end))) - return 0; - - uint16_t j = 0; - for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j) - { - if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) && - pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end))) - return 0; - } - return 1; -} -static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel9_t* dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) ); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel10_t* dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && - pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ; -} -static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel11_t* dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end)); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel12_t* dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end)); -} -static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_dlsch_pdu_rel13_t* dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) && - pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) && - pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end)); -} - -static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel8_t* pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&pch_pdu_rel8->pdu_index, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) && - pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) && - pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end)); -} -static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_pch_pdu_rel13_t* pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) && - pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end)); -} - -static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_prs_pdu_rel9_t* prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; - - return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) && - pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end)); -} - -static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel10_t* csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; - - return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) && - pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) && - pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) && - pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end)); -} - -static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_csi_rs_pdu_rel13_t* csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; - - if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) && - pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end))) - return 0; - - - uint16_t idx =0; - for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx) - { - if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end))) - return 0; - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n"); - //pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??); - } - return 1; -} - -static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel11_t* epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) && - pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) && - pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) && - pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end)); -} - -static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_epdcch_parameters_rel13_t* epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; - - return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) && - pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end)); -} - -static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_mpdcch_pdu_rel13_t* mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; - - - return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) && - pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) && - pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end)); -} - - -static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_nbch_pdu_rel13_t* nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&nbch_params_rel13->pdu_index, end) && - pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) && - pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end)); -} - -static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_npdcch_pdu_rel13_t* npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&npdcch_params_rel13->pdu_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) && - pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end)); -} - -static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_dl_config_ndlsch_pdu_rel13_t* ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; - - return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) && - pull16(ppReadPackedMsg, (uint16_t *)&ndlsch_params_rel13->pdu_index, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && - pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && - pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); -} - - -static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)msg; - - if(!(pull16(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->PDUType, end) )) - return 0; - - - // first match the pdu type, then call the respective function - switch(value->PDUType) - { - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - { - if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - { - if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - { - if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - { - if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); - } - break; - } - - return 1; -} - - - - -static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) && - pull8(ppReadPackedMsg, &value->number_dci, end) && - pull16(ppReadPackedMsg, &value->number_pdu, end) && - pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) && - pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end))) - return 0; - - if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU); - return 0; - } - - if(value->number_pdu) - { - value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config); - if(value->dl_config_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu); - return 0; - } - } - else - { - value->dl_config_pdu_list = 0; - } - - uint16_t i; - uint16_t total_number_of_pdus = value->number_pdu; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end of beyond buffer end - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_BCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_MCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_PCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_PRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value}, - { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - - } - break; - case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - - } - break; - default: - // Need to log an error - break; - } - } - - return 1; -} - - -static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; - - if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && - pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, end) - //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) - )) - return 0; - - int arr[12]; - for(int i=0;idl_tti_request_body.nGroup;i++) - { - for(int j=0;jdl_tti_request_body.nUe[i];j++) - { - arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; - } - if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) - return 0; - } - - for(int i=0;idl_tti_request_body.nPDUs;i++) - { - if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) - return 0; - } - -return 1; -} - - -static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_prach_pdu_t* prach_pdu = (nfapi_nr_prach_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && - pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && - pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && - pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_pucch_pdu_t* pucch_pdu = (nfapi_nr_pucch_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && - pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && - pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && - pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && - pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && - pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && - pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && - pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && - pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && - pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && - pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && - pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && - pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && - pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_pusch_pdu_t* pusch_pdu = (nfapi_nr_pusch_pdu_t*)tlv; - - if (!( - pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && - pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && - pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && - pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && - pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && - pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && - pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && - pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && - pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && - pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && - pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && - pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && - pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && - pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && - pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && - pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && - pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) - // TODO: ignoring beamforming tlv for now - )) - return 0; - - - //Pack Optional Data only included if indicated in pduBitmap - switch(pusch_pdu->pdu_bit_map){ - case PUSCH_PDU_BITMAP_PUSCH_DATA: - { - // pack optional TLVs - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && - pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && - pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_UCI: - { - return( - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && - pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_PUSCH_PTRS: - { - return( - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && -+ pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && -+ pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) - ); - } - break; - - case PUSCH_PDU_BITMAP_DFTS_OFDM: - { - return( - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && - pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && - pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) - ); - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); - } - } - - return 1; -} - - -static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nr_srs_pdu_t* srs_pdu = (nfapi_nr_srs_pdu_t*)tlv; - - return( - pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && - pull32(ppReadPackedMsg, &srs_pdu->handle, end) && - pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && - pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && - pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && - pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && - pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && - pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && - pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && - pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && - pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && - pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && - pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && - pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && - pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && - pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && - pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && - pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && - pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) - // TODO: ignoring beamforming tlv for now - ); -} - - -static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_tti_request_number_of_pdus_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t*)msg; - - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) - return 0; - - - // first natch the pdu type, then call the respective function - switch(pNfapiMsg->pdu_type) - { - - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - { - if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - { - if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - { - if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - { - if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) - return 0; - } - break; - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); - } - break; - - - } - - return 1; -} - - -static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_tti_request_number_of_groups_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t*)msg; - - if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) - return 0; - for (int i = 0; i < pNfapiMsg->n_ue; i++) - { - if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx ,end) ) - return 0; - } - return 1; -} - - -static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; - - if (!( - pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end) )) - return 0; - - for(int i=0; i< pNfapiMsg->n_pdus; i++) - { - if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) - return 0; - } - - for(int i=0; i< pNfapiMsg->n_group; i++) - { - if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) - return 0; - } - - return 1; -} - - - -static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value}, - }; - - return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - - - - nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); -} - -static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) & - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end)); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; - - return ( pull8(ppReadPackedMsg, &ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel11->dmrs_config_flag, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end)); -} -static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &ulsch_pdu_rel13->ue_type, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) && - pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) && - pull8(ppReadPackedMsg, &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end)); -} -static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end)); -} - -static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end))) - return 0; - - switch(cqi_ri_info_rel9->report_type) - { - case NFAPI_CSI_REPORT_TYPE_PERIODIC: - { - if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) && - pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end))) - return 0; - } - break; - case NFAPI_CSI_REPORT_TYPE_APERIODIC: - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0) - return 0; - - uint8_t i; - for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0) - return 0; - - uint8_t j; - for(j = 0; j < 8; ++j) - { - if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0) - return 0; - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); - return 0; - } - break; - }; - return 1; -} - -// NOTE : This function is a little unconventional as we uese the side to -// determine the report type -static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; - if(cqi_ri_info_rel13->tl.length == 0) - { - cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC; - } - else - { - cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC; - if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0) - return 0; - } - return 1; -} -static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) && - pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end)); -} -static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) && - pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end)); -} - -static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end)); -} - -static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) && - pull16(ppReadPackedMsg, (uint16_t *)&ue_info_rel8->rnti, end)); -} -static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) && - pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end)); -} -static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) && - pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) && - pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) && - pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end)); -} - -static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) && - pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end)); -} -static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) && - pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end)); -} -static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) && - pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) && - pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end)); -} - -static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; - - return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end)); -} - -static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) && - pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) && - pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) && - pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) && - pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; - - return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) && - pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end)); -} - -static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) && - pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end)); -} - - -static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; - - return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) && - pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) && - pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end)); -} - -static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; - return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end); -} - -static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end)); -} - -static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; - - return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end)); -} - -static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && - pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && - pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && - pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end))) - return 0; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, - { NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value}, - }; - - return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0); -} - -static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) && - pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) && - pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end)); -} - - -static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - #define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, - - #define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value}, - - #define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\ - { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value}, - - #define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value}, - - #define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, - - #define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value}, - - #define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value}, - - #define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \ - { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value}, - - #define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \ - { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value}, - - #define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value}, - - #define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \ - { NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value}, - - - nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) && - pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) && - pull8(ppReadPackedMsg, &value->srs_present, end))) - return 0; - - if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config); - - if(value->ul_config_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->ul_config_pdu_list = 0; - } - - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end is past buffer end - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - - case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu) - UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu) - UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu) - UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information) - UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information) - UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information) - UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_SRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu) - UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information) - UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu) - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - } - } - return 1; -} - - -static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; - - return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) && - pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) && - pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) && - pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) && - pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) && - pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; - - return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) && - pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end)); -} - -static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; - - return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) && - pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end)); -} - -static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) && - pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) && - pull8(ppReadPackedMsg, &value->resource_block_assignment, end) && - pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) && - pull8(ppReadPackedMsg, &value->start_symbol, end) && - pull8(ppReadPackedMsg, &value->ecce_index, end) && - pull8(ppReadPackedMsg, &value->aggreagation_level, end) && - pull8(ppReadPackedMsg, &value->rnti_type, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->ce_mode, end) && - pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) && - pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) && - pull16(ppReadPackedMsg, &value->transmission_power, end) && - pull8(ppReadPackedMsg, &value->dci_format, end) && - pull8(ppReadPackedMsg, &value->resource_block_start, end) && - pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &value->mcs, end) && - pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) && - pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) && - pull8(ppReadPackedMsg, &value->new_data_indication, end) && - pull8(ppReadPackedMsg, &value->harq_process, end) && - pull8(ppReadPackedMsg, &value->redudency_version, end) && - pull8(ppReadPackedMsg, &value->tpc, end) && - pull8(ppReadPackedMsg, &value->csi_request, end) && - pull8(ppReadPackedMsg, &value->ul_inex, end) && - pull8(ppReadPackedMsg, &value->dai_presence_flag, end) && - pull8(ppReadPackedMsg, &value->dl_assignment_index, end) && - pull8(ppReadPackedMsg, &value->srs_request, end) && - pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) && - pull32(ppReadPackedMsg, &value->tcp_bitmap, end) && - pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) && - pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) && - pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end)); -} - -static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->ncce_index, end) && - pull8(ppReadPackedMsg, &value->aggregation_level, end) && - pull8(ppReadPackedMsg, &value->start_symbol, end) && - pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) && - pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) && - pull8(ppReadPackedMsg, &value->subcarrier_indication, end) && - pull8(ppReadPackedMsg, &value->resource_assignment, end) && - pull8(ppReadPackedMsg, &value->scheduling_delay, end) && - pull8(ppReadPackedMsg, &value->mcs, end) && - pull8(ppReadPackedMsg, &value->redudancy_version, end) && - pull8(ppReadPackedMsg, &value->repetition_number, end) && - pull8(ppReadPackedMsg, &value->new_data_indicator, end) && - pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end)); -} - -static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) && - pull8(ppReadPackedMsg, &value->number_of_dci, end) && - pull8(ppReadPackedMsg, &value->number_of_hi, end))) - return 0; - - uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci; - - if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU); - return 0; - } - - if(totalNumPdus > 0) - { - value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config); - if(value->hi_dci0_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus); - return 0; - } - } - else - { - value->hi_dci0_pdu_list = 0; - } - - uint8_t i; - for(i = 0; i < totalNumPdus; ++i) - { - nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - { - // pdu end if past buffer end - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end); - return 0; - } - - switch(pdu->pdu_type) - { - case NFAPI_HI_DCI0_HI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, - { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, - { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, - { NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); - } - break; - }; - } - - return 1; -} -//unpack_ul_dci_pdu_list_value - -static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; - for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) - { - if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && - - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && - - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) - - return 0; - } - - return (pull16(ppReadPackedMsg, &value->PDUType, end) && - pull16(ppReadPackedMsg, &value->PDUSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && - pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && - - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && - pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && - pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); - -} - -static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ -nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) - )) - return 0; - for(int i=0; i< pNfapiMsg->numPdus; i++) - { - if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) - return 0; - } - - return 1; - -} - -static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - -} -static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) -{ - nfapi_nr_pdu_t* pNfapiMsg = (nfapi_nr_pdu_t*)msg; - - if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) - )) - return 0; - - uint16_t i = 0; - uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; - for(; i < total_number_of_tlvs; ++i) - { - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) - return 0; - - switch(pNfapiMsg->TLVs[i].tag){ - case 0: - { - if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, 16384, pNfapiMsg->TLVs[i].length, end)) - return 0; - break; - - } - - case 1: - { - if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, pNfapiMsg->TLVs[i].length , pNfapiMsg->TLVs[i].length, end)) - return 0; - break; - - } - - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); - break; - } - - } - } - - - return 1; -} - -static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; - - if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && - pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) - return 0; - - for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) - { - if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) - return 0; - } - - return 1; -} - -static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; - - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; - - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_TX_REQUEST_BODY_TAG: - { - pNfapiMsg->tx_request_body.tl = generic_tl; - - if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0) - return 0; - - if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU); - return 0; - } - - if(pNfapiMsg->tx_request_body.number_of_pdus > 0) - { - pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config); - if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus); - return 0; - } - } - else - { - pNfapiMsg->tx_request_body.tx_pdu_list = 0; - } - - - uint16_t i; - uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus; - for(i = 0; i < totalNumPdus; ++i) - { - nfapi_tx_request_pdu_t* pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); - if (pdu) { - uint16_t length = 0; - uint16_t index = 0; - - if(!(pull16(ppReadPackedMsg, &length, end) && - pull16(ppReadPackedMsg, &index, end))) - return 0; - - pdu->pdu_length = length; - pdu->pdu_index = index; - - - // TODO : May need to rethink this bit - pdu->num_segments = 1; - pdu->segments[0].segment_length = pdu->pdu_length; - pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); - - if(pdu->segments[0].segment_data) - { - if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) - return 0; - if (pdu->segments[0].segment_length == 3) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, - pdu->segments[0].segment_data[0], - pdu->segments[0].segment_data[1], - pdu->segments[0].segment_data[2] - ); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); - } - break; - }; - } - - return 1; -} - -static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; - - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; - - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_UE_RELEASE_BODY_TAG: - { - pNfapiMsg->ue_release_request_body.tl = generic_tl; - if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) - return 0; - - if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); - return 0; - } else { - uint8_t j; - uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; - for(j = 0; j < num; ++j){ - if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){ - return 0; - } - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); - } - break; - }; - } - - return 1; -} - -static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->value_0, end) && - pull8(ppReadPackedMsg, &value->value_1, end)); -} - -static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_multiplexing_t* value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->value_0, end) && - pull8(ppReadPackedMsg, &value->value_1, end) && - pull8(ppReadPackedMsg, &value->value_2, end) && - pull8(ppReadPackedMsg, &value->value_3, end)); -} -static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_special_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t*)tlv; - return ( pull8(ppReadPackedMsg, &value->value_0, end)); -} -static uint8_t unpack_harq_indication_tdd_harq_data(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_harq_data_t* value = (nfapi_harq_indication_tdd_harq_data_t*)tlv; - return (pull8(ppReadPackedMsg, &value->value_0, end)); -} - -static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel8_t* value = (nfapi_harq_indication_tdd_rel8_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = 1; - break; - default: - // TODO add error message - return 0; - break; - } - return result; -} - -static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel9_t* value = (nfapi_harq_indication_tdd_rel9_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) - { - // TODO : add error message - return 0; - } - - uint16_t idx = 0; - for(idx = 0; idx < value->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); - break; - default: - // TODO add error message - return 0; - break; - } - - if(result == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_tdd_rel13_t* value = (nfapi_harq_indication_tdd_rel13_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->mode, end) && - pull16(ppReadPackedMsg, &value->number_of_ack_nack, end))) - return 0; - - if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) - { - // TODO : add error message - return 0; - } - - uint16_t idx = 0; - for(idx = 0; idx < value->number_of_ack_nack; ++idx) - { - uint8_t result = 0; - switch(value->mode) - { - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: - result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end); - break; - case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: - result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end); - break; - default: - // TODO add error message - return 0; - break; - } - - if(result == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel8_t* value = (nfapi_harq_indication_fdd_rel8_t*)tlv; - return (pull8(ppReadPackedMsg, &value->harq_tb1, end) && - pull8(ppReadPackedMsg, &value->harq_tb2, end)); -} - -static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel9_t* value = (nfapi_harq_indication_fdd_rel9_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mode, end) && - pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) && - pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end)); -} - -static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_harq_indication_fdd_rel13_t* value = (nfapi_harq_indication_fdd_rel13_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->mode, end) && - pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) && - pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end)); -} - -static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; - - return (pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull8(ppReadPackedMsg, &value->channel, end)); -} - - - -static uint8_t unpack_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; - uint8_t* harqBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(harqBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) - return 0; - - if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); - return 0; - } - - value->harq_pdu_list = (nfapi_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config); - if(value->harq_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_harqs; ++i) - { - nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value}, - { NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value}, - { NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value}, - { NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value}, - { NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value}, - { NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value}, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_crc_indication_rel8_t* crc_pdu_rel8 = (nfapi_crc_indication_rel8_t*)tlv; - return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) ); -} - -static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; - uint8_t* crcBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(crcBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0) - return 0; - - if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU); - return 0; - } - - if(value->number_of_crcs > 0) - { - value->crc_pdu_list = (nfapi_crc_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config); - if(value->crc_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs); - return 0; - } - } - else - { - value->crc_pdu_list = 0; - } - - - uint8_t i = 0; - for(i = 0; i < value->number_of_crcs; ++i) - { - nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0) - return 0; - } - - return 1; -} - -static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->length, end) && - pull16(ppReadPackedMsg, &value->offset, end) && - pull8(ppReadPackedMsg, &value->ul_cqi, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end)); -} -static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; - return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end)); -} - -static uint8_t unpack_rx_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; - - // the rxBodyEnd points to the end of the cqi PDU's - uint8_t* rxBodyEnd = *ppReadPackedMsg + value->tl.length; - uint8_t* rxPduEnd = rxBodyEnd; - - uint8_t* numberOfPdusAddress = *ppReadPackedMsg; - - if(rxBodyEnd > end) - { - // pdu end is past buffer end - return 0; - } - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->rx_pdu_list = (nfapi_rx_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config); - if(value->rx_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->rx_pdu_list = 0; - } - - uint8_t i = 0; - nfapi_rx_indication_pdu_t* pdu = 0; - while((uint8_t*)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t*)(*ppReadPackedMsg) < rxPduEnd) - { - nfapi_tl_t generic_tl; - if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_RX_UE_INFORMATION_TAG: - { - pdu = &(value->rx_pdu_list[i++]); - pdu->rx_ue_information.tl = generic_tl; - if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) - return 0; - } - break; - case NFAPI_RX_INDICATION_REL8_TAG: - { - if(pdu != 0) - { - pdu->rx_indication_rel8.tl = generic_tl; - if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0) - return 0; - - if(pdu->rx_indication_rel8.offset > 0) - { - // Need to check that the data is within the tlv - if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd) - { - // If this the first pdu set the rxPduEnd - if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd) - { - rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset; - - if(rxPduEnd > end) - { - // pdu end is past buffer end - return 0; - } - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n"); - } - } - } - } - break; - case NFAPI_RX_INDICATION_REL9_TAG: - { - if(pdu != 0) - { - pdu->rx_indication_rel9.tl = generic_tl; - if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0) - return 0; - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag ); - } - break; - } - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_pdus; ++idx) - { - if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) - { - uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length; - value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config); - if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0) - { - return 0; - } - } - } - - return 1; -} - -static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel8_t* preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) && - pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) && - pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end)); -} - -static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel9_t* preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; - return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end); -} - -static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_preamble_pdu_rel13_t* preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; - return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end); -} - -static uint8_t unpack_rach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; - uint8_t* rachBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(rachBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0) - return 0; - - if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU); - return 0; - } - - if(value->number_of_preambles > 0) - { - value->preamble_list = (nfapi_preamble_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config); - if(value->preamble_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles); - return 0; - } - } - else - { - value->preamble_list = 0; - } - - - uint8_t i = 0; - for(i = 0; i < value->number_of_preambles; ++i) - { - nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value }, - { NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value }, - { NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel8_t* srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) && - pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) && - pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) && - pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) && - pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end))) - return 0; - return 1; -} - -static uint8_t unpack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel9_t* srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; - return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end)); -} - -static uint8_t unpack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_ttd_rel10_t* srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; - return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end)); -} - -static uint8_t unpack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_srs_indication_fdd_rel11_t* srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; - return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end)); -} - -static uint8_t unpack_tdd_channel_measurement_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; - - if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && - pull8(ppReadPackedMsg, &value->number_of_subbands, end) && - pull8(ppReadPackedMsg, &value->num_atennas, end))) - return 0; - - if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS) - { - // todo : add error - return 0; - } - - if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS) - { - // todo : add error - return 0; - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_subbands; ++idx) - { - if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) && - pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end))) - return 0; - } - - return 1; -} - - -static uint8_t unpack_srs_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_body_t* value = (nfapi_srs_indication_body_t*)tlv; - uint8_t* srsBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(srsBodyEnd > end) - return 0; - - if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0) - return 0; - - if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU); - return 0; - } - - if(value->number_of_ues > 0) - { - value->srs_pdu_list = (nfapi_srs_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config); - if(value->srs_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues); - return 0; - } - } - else - { - value->srs_pdu_list = 0; - } - - - - uint8_t i = 0; - for(i = 0; i < value->number_of_ues; ++i) - { - nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); - - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value}, - { NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value}, - { NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value}, - { NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value}, - { NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value}, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0) - return 0; - } - return 1; -} - -static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; - uint8_t* srBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(srBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0) - return 0; - - if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU); - return 0; - } - - if(value->number_of_srs > 0) - { - value->sr_pdu_list = (nfapi_sr_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config); - if(value->sr_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs); - return 0; - } - } - else - { - value->sr_pdu_list = 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_srs; ++i) - { - nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value }, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0) - return 0; - } - - return 1; - -} - -static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} -static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; - - return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end)); - -} - -static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; - - if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) && - pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end))) - return 0; - - if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n"); - return 0; - } - - if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) && - pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end))) - return 0; - - return 1; -} - -static uint8_t unpack_cqi_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; - - // the cqiBodyEnd points to the end of the cqi PDU's - uint8_t* cqiBodyEnd = *ppReadPackedMsg + value->tl.length; - - //uint8_t* cqiPduEnd = cqiBodyEnd; - //uint8_t* numberOfPdusAddress = *ppReadPackedMsg; - - if(cqiBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0) - return 0; - - if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU); - return -1; - } - - if(value->number_of_cqis > 0) - { - value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config); - if(value->cqi_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); - return 0; - } - } - else - { - value->cqi_pdu_list = 0; - } - - if(value->number_of_cqis > 0) - { - value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config); - if(value->cqi_raw_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); - return 0; - } - } - else - { - value->cqi_raw_pdu_list = 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_cqis; ++i) - { - nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); - memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t)); - - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - - while((uint8_t*)(*ppReadPackedMsg) < cqiPduInstanceEnd) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_RX_UE_INFORMATION_TAG: - pdu->rx_ue_information.tl = generic_tl; - if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) - return 0; - break; - case NFAPI_CQI_INDICATION_REL8_TAG: - pdu->cqi_indication_rel8.tl = generic_tl; - if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0) - return 0; - - break; - case NFAPI_CQI_INDICATION_REL9_TAG: - pdu->cqi_indication_rel9.tl = generic_tl; - if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0) - return 0; - - break; - case NFAPI_UL_CQI_INFORMATION_TAG: - pdu->ul_cqi_information.tl = generic_tl; - if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0) - return 0; - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag ); - } - break; - - }; - } - } - - uint8_t idx = 0; - for(idx = 0; idx < value->number_of_cqis; ++idx) - { - if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) - { - if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0) - return 0; - } - else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) - { - if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0) - return 0; - } - } - - - return 1; - -} - -static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} -static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->mp_cca, end) && - pull32(ppReadPackedMsg, &value->n_cca, end) && - pull32(ppReadPackedMsg, &value->offset, end) && - pull32(ppReadPackedMsg, &value->lte_txop_sf, end) && - pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) && - pull32(ppReadPackedMsg, &value->lbt_mode, end)); -} - -static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->offset, end) && - pull16(ppReadPackedMsg, &value->sfn_sf_end, end) && - pull32(ppReadPackedMsg, &value->lbt_mode, end)); -} - - -static uint8_t unpack_lbt_config_request_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU); - return 0; - } - - if(value->number_of_pdus) - { - value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config); - if(value->lbt_dl_config_req_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->lbt_dl_config_req_pdu_list = 0; - } - - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type); - return 0; - } - } - - return 1; -} -static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->result, end) && - pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) && - pull32(ppReadPackedMsg, &value->initial_partial_sf, end)); - -} -static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; - - return (pull32(ppReadPackedMsg, &value->handle, end) && - pull32(ppReadPackedMsg, &value->result, end)); -} - -static uint8_t unpack_lbt_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; - - if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) - return 0; - - if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU); - return 0; - } - - if(value->number_of_pdus > 0) - { - value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config); - if(value->lbt_indication_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); - return 0; - } - } - else - { - value->lbt_indication_pdu_list = 0; - } - - uint16_t i; - uint16_t total_number_of_pdus = value->number_of_pdus; - for(i = 0; i < total_number_of_pdus; ++i) - { - nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); - - if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && - pull8(ppReadPackedMsg, &pdu->pdu_size, end))) - return 0; - - uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; - - if(packedPduEnd > end) - return 0; - - switch(pdu->pdu_type) - { - case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: - { - unpack_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value}, - }; - - unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); - } - break; - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type); - return 0; - } - } - - return 1; -} -static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nb_harq_indication_fdd_rel13_t* value = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; - return (pull8(ppReadPackedMsg, &value->harq_tb1, end)); -} - - -static uint8_t unpack_nb_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; - uint8_t* nbharqBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(nbharqBodyEnd > end) - return 0; - - if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) - return 0; - - if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); - return 0; - } - - value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config); - if(value->nb_harq_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_harqs; ++i) - { - nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); - if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) - return 0; - - uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, - { NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value}, - { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) -{ - nfapi_nrach_indication_pdu_rel13_t* value = (nfapi_nrach_indication_pdu_rel13_t*)tlv; - - return (pull16(ppReadPackedMsg, &value->rnti, end) && - pull8(ppReadPackedMsg, &value->initial_sc, end) && - pull16(ppReadPackedMsg, &value->timing_advance, end) && - pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); -} - -static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){ - return 0; - } - else{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); - } - return 1; -} - -static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; - uint8_t* nrachBodyEnd = *ppReadPackedMsg + value->tl.length; - - if(nrachBodyEnd > end) - return 0; - - if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0) - return 0; - - if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU); - return 0; - } - - value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config); - if(value->nrach_pdu_list == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected); - return 0; - } - - uint8_t i = 0; - for(i = 0; i < value->number_of_initial_scs_detected; ++i) - { - nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); - - uint8_t* nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6; - - unpack_tlv_t unpack_fns[] = - { - { NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value}, - }; - - if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0) - return 0; - - } - - return 1; -} - -static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - { NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value}, - }; - - return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_nr_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_slot, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_nr_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - -static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - -static uint8_t unpack_nr_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; - - unpack_p7_tlv_t unpack_fns[] = - { - }; - - return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->last_slot, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->dl_tti_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_tti_jitter, end) && - pull32(ppReadPackedMsg, &pNfapiMsg->ul_dci_jitter, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_latest_delay, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_earliest_arrival, end) && - pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_earliest_arrival, end) && - unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); -} - - - -// unpack length check - -static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t)) - retLen = sizeof(nfapi_dl_config_request_t); - break; - - case NFAPI_UL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t)) - retLen = sizeof(nfapi_ul_config_request_t); - break; - - case NFAPI_SUBFRAME_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) - retLen = sizeof(nfapi_subframe_indication_t); - break; - - case NFAPI_HI_DCI0_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t)) - retLen = sizeof(nfapi_hi_dci0_request_t); - break; - - case NFAPI_TX_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_tx_request_t)) - retLen = sizeof(nfapi_tx_request_t); - break; - - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); - break; - - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); - break; - - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); - break; - - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; - - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; - - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; - - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - - case NFAPI_DL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t)) - retLen = sizeof(nfapi_dl_node_sync_t); - break; - - case NFAPI_UL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t)) - retLen = sizeof(nfapi_ul_node_sync_t); - break; - - case NFAPI_TIMING_INFO: - if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) - retLen = sizeof(nfapi_timing_info_t); - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) - retLen = sizeof(nfapi_ue_release_request_t); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) - retLen = sizeof(nfapi_ue_release_response_t); - break; - - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } - - return retLen; -} - -static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) -{ - int retLen = 0; - - switch (msgId) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) - retLen = sizeof(nfapi_nr_dl_tti_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) - retLen = sizeof(nfapi_nr_ul_tti_request_t); - break; - - case NFAPI_SUBFRAME_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) - retLen = sizeof(nfapi_subframe_indication_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) - retLen = sizeof(nfapi_nr_ul_dci_request_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) - retLen = sizeof(nfapi_nr_tx_data_request_t); - break; - - case NFAPI_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) - retLen = sizeof(nfapi_harq_indication_t); - break; - - case NFAPI_CRC_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) - retLen = sizeof(nfapi_crc_indication_t); - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) - retLen = sizeof(nfapi_rx_indication_t); - break; - - case NFAPI_RACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) - retLen = sizeof(nfapi_rach_indication_t); - break; - - case NFAPI_SRS_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) - retLen = sizeof(nfapi_srs_indication_t); - break; - - case NFAPI_RX_SR_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) - retLen = sizeof(nfapi_sr_indication_t); - break; - - case NFAPI_RX_CQI_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) - retLen = sizeof(nfapi_cqi_indication_t); - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) - retLen = sizeof(nfapi_lbt_dl_config_request_t); - break; - - case NFAPI_LBT_DL_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) - retLen = sizeof(nfapi_lbt_dl_indication_t); - break; - - case NFAPI_NB_HARQ_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) - retLen = sizeof(nfapi_nb_harq_indication_t); - break; - - case NFAPI_NRACH_INDICATION: - if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) - retLen = sizeof(nfapi_nrach_indication_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) - retLen = sizeof(nfapi_nr_dl_node_sync_t); - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) - retLen = sizeof(nfapi_nr_ul_node_sync_t); - break; - - case NFAPI_TIMING_INFO: - if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) - retLen = sizeof(nfapi_timing_info_t); - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) - retLen = sizeof(nfapi_ue_release_request_t); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) - retLen = sizeof(nfapi_ue_release_response_t); - break; - - default: - NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); - break; - } - - return retLen; -} - - - -// Main unpack functions - public - -int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - return -1; - - return 0; -} - -int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - int result = 0; - nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - /* - uint8_t *ptr = pMessageBuf; - printf("\n Read P7 message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); -*/ - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); - - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; - } - - if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); - return -1; - } - - /* - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); - return -1; - } - */ - - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_DL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_TX_REQUEST: - if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) - result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_HI_DCI0_REQUEST: - if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) - result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_HARQ_INDICATION: - if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_CRC_INDICATION: - if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RACH_INDICATION: - if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_SRS_INDICATION: - if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_SR_INDICATION: - if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_CQI_INDICATION: - if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_INDICATION: - if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_DL_NODE_SYNC: - if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UL_NODE_SYNC: - if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen)) - result = unpack_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_TIMING_INFO: - if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) - result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - default: - - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p7_vendor_extension) - { - result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } - - if(result == 0) - return -1; - else - return 0; -} - -int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) -{ - int result = 0; - nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; - uint8_t *pReadPackedMessage = pMessageBuf; - uint8_t *end = pMessageBuf + messageBufLen; - - if (pMessageBuf == NULL || pUnpackedBuf == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); - return -1; - } - - if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); - return -1; - } - /* - uint8_t *ptr = pMessageBuf; - printf("\n Read P7 message unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); -*/ - // clean the supplied buffer for - tag value blanking - (void)memset(pUnpackedBuf, 0, unpackedBufLen); - - // process the header - if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && - pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && - pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && - pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && - pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); - return -1; - } - - if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); - return -1; - } - - /* - if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); - return -1; - } - */ - - // look for the specific message - switch (pMessageHeader->message_id) - { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) - result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) - result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) - result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) - result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_REQUEST: - if (check_nr_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) - result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) - result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_ULSCH_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) - result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) - result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) - result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_SR_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) - result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_RX_CQI_INDICATION: - if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) - result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_CONFIG_REQUEST: - if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) - result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_LBT_DL_INDICATION: - if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) - result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NB_HARQ_INDICATION: - if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) - result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NRACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) - result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) - result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) - result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); - else - return -1; - break; - - case NFAPI_TIMING_INFO: - if (check_nr_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) - result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (check_nr_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - - default: - - if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && - pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) - { - if(config && config->unpack_p7_vendor_extension) - { - result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); - } - } - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); - } - break; - } - - if(result == 0) - return -1; - else - return 0; -} - - +/* + * Copyright 2017 Cisco Systems, Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "nfapi_nr_interface_scf.h" + +extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, void* user_data); +extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedMsg, void* user_data); + +uint32_t nfapi_calculate_checksum(uint8_t* buffer, uint16_t len) +{ + uint32_t chksum = 0; + // calcaulte upto the checksum + chksum = crc32(chksum, buffer, 8); + + // skip the checksum + uint8_t zeros[4] = {0, 0, 0, 0}; + chksum = crc32(chksum, zeros, 4); + + // continu with the rest of the mesage + chksum = crc32(chksum, &buffer[NFAPI_P7_HEADER_LENGTH], len - NFAPI_P7_HEADER_LENGTH); + + // return the inverse + return ~(chksum); +} + +int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len) +{ + uint32_t checksum = nfapi_calculate_checksum(buffer, len); + + uint8_t* p_write = &buffer[8]; + return (push32(checksum, &p_write, buffer + len) > 0 ? 0 : -1); +} + +int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp) +{ + uint8_t* p_write = &buffer[12]; + return (push32(timestamp, &p_write, buffer + 16) > 0 ? 0 : -1); +} + +uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len) +{ + return nfapi_calculate_checksum(buffer, len); +} + +void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config) +{ + if(size == 0) + return 0; + + void* buffer_p = NULL; + if(config && config->allocate) + { + buffer_p = (config->allocate)(size); + if(buffer_p != NULL){ + memset(buffer_p,0,size); + } + return buffer_p; + } + else + { + buffer_p = calloc(1, size); + return buffer_p; + } +} + +void nfapi_p7_deallocate(void* ptr, nfapi_p7_codec_config_t* config) +{ + if(ptr == NULL) + return; + + if(config && config->deallocate) + { + return (config->deallocate)(ptr); + } + else + { + return free(ptr); + } +} +// Pack routines + + +static uint8_t pack_dl_config_dci_dl_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel8_t* value = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; + + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci_format:%u\n", __FUNCTION__, value->dci_format); + + return ( push8(value->dci_format, ppWritePackedMsg, end) && + push8(value->cce_idx, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs_1, ppWritePackedMsg, end) && + push8(value->redundancy_version_1, ppWritePackedMsg, end) && + push8(value->new_data_indicator_1, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->mcs_2, ppWritePackedMsg, end) && + push8(value->redundancy_version_2, ppWritePackedMsg, end) && + push8(value->new_data_indicator_2, ppWritePackedMsg, end) && + push8(value->harq_process, ppWritePackedMsg, end) && + push8(value->tpmi, ppWritePackedMsg, end) && + push8(value->pmi, ppWritePackedMsg, end) && + push8(value->precoding_information, ppWritePackedMsg, end) && + push8(value->tpc, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end) && + push8(value->transport_block_size_index, ppWritePackedMsg, end) && + push8(value->downlink_power_offset, ppWritePackedMsg, end) && + push8(value->allocate_prach_flag, ppWritePackedMsg, end) && + push8(value->preamble_index, ppWritePackedMsg, end) && + push8(value->prach_mask_index, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel9_t* value = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; + + return( push8(value->mcch_flag, ppWritePackedMsg, end) && + push8(value->mcch_change_notification, ppWritePackedMsg, end) && + push8(value->scrambling_identity, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel10_t* value = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; + + return ( push8(value->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && + push8(value->carrier_indicator, ppWritePackedMsg, end) && + push8(value->srs_flag, ppWritePackedMsg, end) && + push8(value->srs_request, ppWritePackedMsg, end) && + push8(value->antenna_ports_scrambling_and_layers, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(value->n_dl_rb, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel11_t* value = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; + + return ( push8(value->harq_ack_resource_offset, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_quasi_co_location_indicator, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_dci_dl_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel12_t* value = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; + + return ( push8(value->primary_cell_type, ppWritePackedMsg, end) && + push8(value->ul_dl_configuration_flag, ppWritePackedMsg, end) && + push8(value->number_ul_dl_configurations, ppWritePackedMsg, end) && + pusharray8(value->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, value->number_ul_dl_configurations, ppWritePackedMsg, end)); +} + +static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t* value, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + if (!( push8(value->num_prb_per_subband, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->num_antennas, ppWritePackedMsg, end))) + return 0; + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) + { + nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); + + if(!(push8(subband_info->subband_index, ppWritePackedMsg, end) && + push8(subband_info->scheduled_ues, ppWritePackedMsg, end))) + return 0; + + + uint8_t antenna_idx = 0; + uint8_t scheduled_ue_idx = 0; + + for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) + { + for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) + { + if(!push16(subband_info->precoding_value[antenna_idx][scheduled_ue_idx], ppWritePackedMsg, end)) + return 0; + } + } + + } + + + return 1; + +} + + +static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; + + return( + push16(value->bwp_size, ppWritePackedMsg, end) && + push16(value->bwp_start, ppWritePackedMsg, end) && + + push8(value->subcarrier_spacing, ppWritePackedMsg, end) && + push8(value->cyclic_prefix, ppWritePackedMsg, end) && + + push16(value->start_rb, ppWritePackedMsg, end) && + push16(value->nr_of_rbs, ppWritePackedMsg, end) && + + push8(value->csi_type, ppWritePackedMsg, end) && + push8(value->row, ppWritePackedMsg, end) && + + push16(value->freq_domain, ppWritePackedMsg, end) && + push8(value->symb_l0, ppWritePackedMsg, end) && + + push8(value->symb_l1, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + + push8(value->freq_density, ppWritePackedMsg, end) && + push16(value->scramb_id, ppWritePackedMsg, end) && + + push8(value->power_control_offset, ppWritePackedMsg, end) && + push8(value->power_control_offset_ss, ppWritePackedMsg, end) + ); + +} + + +static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + + push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + + push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + pusharray8(value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) + return 0; + + } + + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->BWPSize, ppWritePackedMsg, end) && + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->CceRegMappingType, ppWritePackedMsg, end) && + + push8(value->RegBundleSize, ppWritePackedMsg, end) && + push8(value->InterleaverSize, ppWritePackedMsg, end) && + push8(value->CoreSetType, ppWritePackedMsg, end) && + push16(value->ShiftIndex, ppWritePackedMsg, end) && + + push8(value->precoderGranularity, ppWritePackedMsg, end) && + push16(value->numDlDci, ppWritePackedMsg, end)); + +} + + +static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + printf("packing pdsch pdu. \n"); + nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; + + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->pduBitmap, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->pduIndex, ppWritePackedMsg, end) && + push16(value->BWPSize, ppWritePackedMsg, end) && + + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + push8(value->NrOfCodewords, ppWritePackedMsg, end) && + + pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && + + pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && + pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && + push16(value->dataScramblingId, ppWritePackedMsg, end) && + push8(value->nrOfLayers, ppWritePackedMsg, end) && + + push8(value->transmissionScheme, ppWritePackedMsg, end) && + push8(value->refPoint, ppWritePackedMsg, end) && + push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && + push8(value->dmrsConfigType, ppWritePackedMsg, end) && + + push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && + push8(value->SCID, ppWritePackedMsg, end) && + push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && + push16(value->dmrsPorts, ppWritePackedMsg, end) && + + push8(value->resourceAlloc, ppWritePackedMsg, end) && + push16(value->rbStart, ppWritePackedMsg, end) && + push16(value->rbSize, ppWritePackedMsg, end) && + + push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->NrOfSymbols, ppWritePackedMsg, end) && + push8(value->PTRSPortIndex, ppWritePackedMsg, end) && + + push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && + push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && + push8(value->PTRSReOffset, ppWritePackedMsg, end) + ); + +} + + +static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + printf("Packing ssb. \n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; + + return( + push16(value->PhysCellId, ppWritePackedMsg, end) && + push8(value->BetaPss, ppWritePackedMsg, end) && + push8(value->SsbBlockIndex, ppWritePackedMsg, end) && + push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && + push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && + push8(value->bchPayloadFlag, ppWritePackedMsg, end) && + push32(value->bchPayload, ppWritePackedMsg, end) + // TODO: pack precoding_and_beamforming too + ); + +} + + +static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel13_t* value = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; + + return( push8(value->laa_end_partial_sf_flag, ppWritePackedMsg, end) && + push8(value->laa_end_partial_sf_configuration, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end) && + push8(value->codebook_size_determination, ppWritePackedMsg, end) && + push8(value->drms_table_flag, ppWritePackedMsg, end) && + push8(value->tpm_struct_flag, ppWritePackedMsg, end) && + (value->tpm_struct_flag == 1 ? pack_tpm_value(&(value->tpm), ppWritePackedMsg, end) : 1)); +} + +static uint8_t pack_dl_config_bch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_bch_pdu_rel8_t* value = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; + + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s()\n", __FUNCTION__); + + return( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_mch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_mch_pdu_rel8_t* value = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; + + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->mbsfn_area_id, ppWritePackedMsg, end)); +} + +static uint8_t pack_bf_vector_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_bf_vector_t* bf = (nfapi_bf_vector_t*)elem; + + return ( push8(bf->subband_index, ppWritePackedMsg, end) && + push8(bf->num_antennas, ppWritePackedMsg, end) && + pusharray16(bf->bf_value, NFAPI_MAX_NUM_ANTENNAS, bf->num_antennas, ppWritePackedMsg, end)); + + +} +static uint8_t pack_dl_config_dlsch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel8_t* value = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; + + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->transport_blocks, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->transmission_scheme, ppWritePackedMsg, end) && + push8(value->number_of_layers, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + pusharray8(value->codebook_index, NFAPI_MAX_NUM_SUBBANDS, value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->ue_category_capacity, ppWritePackedMsg, end) && + push8(value->pa, ppWritePackedMsg, end) && + push8(value->delta_power_offset_index, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end) && + push8(value->nprb, ppWritePackedMsg, end) && + push8(value->transmission_mode, ppWritePackedMsg, end) && + push8(value->num_bf_prb_per_subband, ppWritePackedMsg, end) && + push8(value->num_bf_vector, ppWritePackedMsg, end) && + packarray(value->bf_vector, sizeof(nfapi_bf_vector_t), NFAPI_MAX_BF_VECTORS, value->num_bf_vector, ppWritePackedMsg, end, &pack_bf_vector_info)); + +} +static uint8_t pack_dl_config_dlsch_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel9_t* value = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; + return ( push8(value->nscid, ppWritePackedMsg, end) ); +} +static uint8_t pack_dl_config_dlsch_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel10_t* value = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; + + return ( push8(value->csi_rs_flag, ppWritePackedMsg, end) && + push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && + push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && + pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_nzp_configuration, ppWritePackedMsg, end) && + push8(value->pdsch_start, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel11_t* value = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; + + return( push8(value->drms_config_flag, ppWritePackedMsg, end) && + push16(value->drms_scrambling, ppWritePackedMsg, end) && + push8(value->csi_config_flag, ppWritePackedMsg, end) && + push16(value->csi_scrambling, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_flag, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_atenna_ports, ppWritePackedMsg, end) && + push8(value->pdsch_re_mapping_freq_shift, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel12_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel12_t* value = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; + + return( push8(value->altcqi_table_r12, ppWritePackedMsg, end) && + push8(value->maxlayers, ppWritePackedMsg, end) && + push8(value->n_dl_harq, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_dlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel13_t* value = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; + + return( push8(value->dwpts_symbols, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end) && + push8(value->ue_type, ppWritePackedMsg, end) && + push8(value->pdsch_payload_type, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && + push8(value->drms_table_flag, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_pch_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_pch_pdu_rel8_t* value = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; + + return( push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->p_rnti, ppWritePackedMsg, end) && + push8(value->resource_allocation_type, ppWritePackedMsg, end) && + push8(value->virtual_resource_block_assignment_flag, ppWritePackedMsg, end) && + push32(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->number_of_transport_blocks, ppWritePackedMsg, end) && + push8(value->transport_block_to_codeword_swap_flag, ppWritePackedMsg, end) && + push8(value->transmission_scheme, ppWritePackedMsg, end) && + push8(value->number_of_layers, ppWritePackedMsg, end) && + push8(value->codebook_index, ppWritePackedMsg, end) && + push8(value->ue_category_capacity, ppWritePackedMsg, end) && + push8(value->pa, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->nprb, ppWritePackedMsg, end) && + push8(value->ngap, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_pch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_pch_pdu_rel13_t* value = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; + + return ( push8(value->ue_mode, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_prs_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_prs_pdu_rel9_t* value = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; + + return( push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->prs_bandwidth, ppWritePackedMsg, end) && + push8(value->prs_cyclic_prefix_type, ppWritePackedMsg, end) && + push8(value->prs_muting, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_csi_rs_pdu_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_csi_rs_pdu_rel10_t* value = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; + + return( push8(value->csi_rs_antenna_port_count_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_resource_config_r10, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->csi_rs_zero_tx_power_resource_config_bitmap_r10, ppWritePackedMsg, end) && + push8(value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end) && + pusharray8(value->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, value->csi_rs_number_of_nzp_configuration, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_csi_rs_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_csi_rs_pdu_rel13_t* value = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; + + if(!(push8(value->csi_rs_class, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + push8(value->num_bf_vector, ppWritePackedMsg, end))) + { + return 0; + } + + uint16_t i; + for(i = 0; i < value->num_bf_vector; ++i) + { + if(!(push8(value->bf_vector[i].csi_rs_resource_index, ppWritePackedMsg, end) && + pusharray16(value->bf_vector[i].bf_value, NFAPI_MAX_ANTENNA_PORT_COUNT, NFAPI_MAX_ANTENNA_PORT_COUNT, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} +static uint8_t pack_bf_vector(nfapi_bf_vector_t* vector, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(vector->subband_index, ppWritePackedMsg, end) && + push8(vector->num_antennas, ppWritePackedMsg, end) && + pusharray16(vector->bf_value, NFAPI_MAX_NUM_ANTENNAS, vector->num_antennas, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_epdcch_parameters_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_epdcch_parameters_rel11_t* value = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; + + return ( push8(value->epdcch_resource_assignment_flag, ppWritePackedMsg, end) && + push16(value->epdcch_id, ppWritePackedMsg, end) && + push8(value->epdcch_start_symbol, ppWritePackedMsg, end) && + push8(value->epdcch_num_prb, ppWritePackedMsg, end) && + pusharray8(value->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, value->epdcch_num_prb, ppWritePackedMsg, end) && + pack_bf_vector(&value->bf_vector, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_epdcch_parameters_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_epdcch_parameters_rel13_t* value = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; + + return (push8(value->dwpts_symbols, ppWritePackedMsg, end) && + push8(value->initial_lbt_sf, ppWritePackedMsg, end)); +} +static uint8_t pack_dl_config_mpdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_mpdcch_pdu_rel13_t* value = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; + + return ( push8(value->mpdcch_narrow_band, ppWritePackedMsg, end) && + push8(value->number_of_prb_pairs, ppWritePackedMsg, end) && + push8(value->resource_block_assignment, ppWritePackedMsg, end) && + push8(value->mpdcch_tansmission_type, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->ecce_index, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->ce_mode, ppWritePackedMsg, end) && + push16(value->drms_scrambling_init, ppWritePackedMsg, end) && + push16(value->initial_transmission_sf_io, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push8(value->dci_format, ppWritePackedMsg, end) && + push16(value->resource_block_coding, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->pdsch_reptition_levels, ppWritePackedMsg, end) && + push8(value->redundancy_version, ppWritePackedMsg, end) && + push8(value->new_data_indicator, ppWritePackedMsg, end) && + push8(value->harq_process, ppWritePackedMsg, end) && + push8(value->tpmi_length, ppWritePackedMsg, end) && + push8(value->tpmi, ppWritePackedMsg, end) && + push8(value->pmi_flag, ppWritePackedMsg, end) && + push8(value->pmi, ppWritePackedMsg, end) && + push8(value->harq_resource_offset, ppWritePackedMsg, end) && + push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push8(value->tpc, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index_length, ppWritePackedMsg, end) && + push8(value->downlink_assignment_index, ppWritePackedMsg, end) && + push8(value->allocate_prach_flag, ppWritePackedMsg, end) && + push8(value->preamble_index, ppWritePackedMsg, end) && + push8(value->prach_mask_index, ppWritePackedMsg, end) && + push8(value->starting_ce_level, ppWritePackedMsg, end) && + push8(value->srs_request, ppWritePackedMsg, end) && + push8(value->antenna_ports_and_scrambling_identity_flag, ppWritePackedMsg, end) && + push8(value->antenna_ports_and_scrambling_identity, ppWritePackedMsg, end) && + push8(value->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(value->paging_direct_indication_differentiation_flag, ppWritePackedMsg, end) && + push8(value->direct_indication, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(value->number_of_tx_antenna_ports, ppWritePackedMsg, end) && + pusharray16(value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_config_nbch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_nbch_pdu_rel13_t* value = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; + + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push16(value->transmission_power, ppWritePackedMsg, end) && + push16(value->hyper_sfn_2_lsbs, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_config_npdcch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_npdcch_pdu_rel13_t* value = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; + + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push8(value->ncce_index, ppWritePackedMsg, end) && + push8(value->aggregation_level, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && + push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && + push8(value->dci_format, ppWritePackedMsg, end) && + push8(value->scheduling_delay, ppWritePackedMsg, end) && + push8(value->resource_assignment, ppWritePackedMsg, end) && + push8(value->repetition_number, ppWritePackedMsg, end) && + push8(value->mcs, ppWritePackedMsg, end) && + push8(value->new_data_indicator, ppWritePackedMsg, end) && + push8(value->harq_ack_resource, ppWritePackedMsg, end) && + push8(value->npdcch_order_indication, ppWritePackedMsg, end) && + push8(value->starting_number_of_nprach_repetitions, ppWritePackedMsg, end) && + push8(value->subcarrier_indication_of_nprach, ppWritePackedMsg, end) && + push8(value->paging_direct_indication_differentation_flag, ppWritePackedMsg, end) && + push8(value->direct_indication, ppWritePackedMsg, end) && + push8(value->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push8(value->total_dci_length_including_padding, ppWritePackedMsg, end)); +} + +static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_ndlsch_pdu_rel13_t* value = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; + + return (push16(value->length, ppWritePackedMsg, end) && + push16(value->pdu_index, ppWritePackedMsg, end) && + push8(value->start_symbol, ppWritePackedMsg, end) && + push8(value->rnti_type, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->resource_assignment, ppWritePackedMsg, end) && + push16(value->repetition_number, ppWritePackedMsg, end) && + push8(value->modulation, ppWritePackedMsg, end) && + push8(value->number_of_subframes_for_resource_assignment, ppWritePackedMsg, end) && + push8(value->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && + push16(value->sf_idx, ppWritePackedMsg, end) && + push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); +} + + +static uint8_t pack_dl_tti_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)tlv; + + if(!(push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->PDUType, ppWritePackedMsg, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->PDUType) + { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + { + if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + { + if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + { + if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + { + if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; +} + +static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; + + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() dci:%u pdu:%u pdsch:%u rnti:%u pcfich:%u\n", __FUNCTION__, value->number_dci, value->number_pdu, value->number_pdsch_rnti, value->transmission_power_pcfich); + + if(!(push8(value->number_pdcch_ofdm_symbols, ppWritePackedMsg, end) && + push8(value->number_dci, ppWritePackedMsg, end) && + push16(value->number_pdu, ppWritePackedMsg, end) && + push8(value->number_pdsch_rnti, ppWritePackedMsg, end) && + push16(value->transmission_power_pcfich, ppWritePackedMsg, end))) + { + return 0; + } + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_pdu; + for(; i < total_number_of_pdus; ++i) + { + nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: + { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE\n", __FUNCTION__); + + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value))) + { + return 0; + } + } + break; + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: + { + //NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_DL_CONFIG_BCH_PDU_TYPE\n", __FUNCTION__); + + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_bch_pdu_rel8_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_mch_pdu_rel8_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dlsch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_pch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_prs_pdu_rel9_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_csi_rs_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel8_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel9_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel10_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel11_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel12_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_dci_dl_pdu_rel13_value) && + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel11_value) & + pack_tlv(NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, ppWritePackedMsg, end, &pack_dl_config_epdcch_parameters_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_mpdcch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_nbch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_npdcch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, ppWritePackedMsg, end, &pack_dl_config_ndlsch_pdu_rel13_value))) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + + +static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nGroup , ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nPDUs , ppWritePackedMsg, end) && + pusharray8(pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + for(int i=0;idl_tti_request_body.nGroup;i++) + { + for(int j=0;jdl_tti_request_body.nUe[i];j++) + { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + if(!(pusharrays32(arr,12,pNfapiMsg->dl_tti_request_body.nUe[i],ppWritePackedMsg, end))) + return 0; + } + + for(int i=0;idl_tti_request_body.nPDUs;i++) + { + if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + +static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; + + //return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + //pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value) && + //pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + { + uint8_t x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + uint8_t y = pack_tlv(NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, ppWritePackedMsg, end, &pack_dl_config_request_body_value); + uint8_t z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + + if (!x || !y || !z) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_DL_CONFIG_REQUEST x:%u y:%u z:%u \n", __FUNCTION__,x,y,z); + } + + return x && y && z; + } +} + + + + +static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t * end) +{ + nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; + + return( push32(ulsch_pdu_rel8->handle, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel8->size, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->modulation_type, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->new_data_indication, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->redundancy_version, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->harq_process_number, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->ul_tx_mode, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->current_tx_nb, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel8->n_srs, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ulsch_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; + + return (push8(ulsch_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && + push32(ulsch_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->transport_blocks, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->transmission_scheme, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->number_of_layers, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->codebook_index, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel10->disable_sequence_hopping_flag, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; + + return (push8(ulsch_pdu_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel11->npusch_identity, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel11->dmrs_config_flag, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel11->ndmrs_csh_identity, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; + + return (push8(ulsch_pdu_rel13->ue_type, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push16(ulsch_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && + push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); +} + +//Pack fns for ul_tti PDUS + + +static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t* prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && + push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && + push8(prach_pdu->prach_format, ppWritePackedMsg, end) && + push8(prach_pdu->num_ra, ppWritePackedMsg, end) && + push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && + push16(prach_pdu->num_cs, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); + +} + +static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t* pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(pucch_pdu->rnti, ppWritePackedMsg, end) && + push32(pucch_pdu->handle, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(pucch_pdu->format_type, ppWritePackedMsg, end) && + push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && + push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && + push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && + push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && + push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && + push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && + push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && + push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); + +} + + +static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t* pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + + if (!( + push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && + push16(pusch_pdu->rnti, ppWritePackedMsg, end) && + push32(pusch_pdu->handle, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && + push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && + push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && + push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && + push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->scid, ppWritePackedMsg, end) && + push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && + push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && + push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && + push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && + push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && + push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map){ + case PUSCH_PDU_BITMAP_PUSCH_DATA: + { + // pack optional TLVs + return( + push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && + push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && + pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: + { + return( + push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: + { + return( + push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: + { + return( + push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && + push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) + ); + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + +static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t* srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(srs_pdu->rnti, ppWritePackedMsg, end) && + push32(srs_pdu->handle, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && + push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && + push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && + push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && + push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && + push8(srs_pdu->config_index, ppWritePackedMsg, end) && + push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && + push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && + push8(srs_pdu->comb_size, ppWritePackedMsg, end) && + push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->resource_type, ppWritePackedMsg, end) && + push16(srs_pdu->t_srs, ppWritePackedMsg, end) && + push16(srs_pdu->t_offset, ppWritePackedMsg, end) + + // TODO: ignoring beamforming tlv for now + ); + +} + +static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu* ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &ulsch_pdu->ulsch_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &ulsch_pdu->ulsch_pdu_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &ulsch_pdu->ulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel13_value)); +} + +static uint8_t pack_ul_config_request_cqi_ri_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; + + return ( push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->ri_size, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->delta_offset_cqi, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel8->delta_offset_ri, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_cqi_ri_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; + + if(!(push8(cqi_ri_info_rel9->report_type, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->delta_offset_cqi, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->delta_offset_ri, ppWritePackedMsg, end))) + { + return 0; + } + + switch(cqi_ri_info_rel9->report_type) + { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: + { + if(!(push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, ppWritePackedMsg, end) && + push8(cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, ppWritePackedMsg, end))) + { + return 0; + } + } + break; + case NFAPI_CSI_REPORT_TYPE_APERIODIC: + { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t i; + for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) + { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, ppWritePackedMsg, end) == 0) + return 0; + + uint8_t j; + for(j = 0; j < 8; ++j) + { + if(push8(cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], ppWritePackedMsg, end) == 0) + return 0; + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); + } + break; + }; + + return 1; +} + +static uint8_t pack_ul_config_request_cqi_ri_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; + + switch(cqi_ri_info_rel13->report_type) + { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: + { + if(push16(cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, ppWritePackedMsg, end) == 0) + return 0; + } + break; + case NFAPI_CSI_REPORT_TYPE_APERIODIC: + { + // No parameters + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel13->report_type ); + } + break; + }; + + return 1; +} + +static uint8_t pack_ul_config_request_cqi_ri_information(nfapi_ul_config_cqi_ri_information* cqi_ri_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return (pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &cqi_ri_info->cqi_ri_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &cqi_ri_info->cqi_ri_information_rel9, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel9_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &cqi_ri_info->cqi_ri_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_ri_rel13_value)); + +} + +static uint8_t pack_ul_config_request_init_tx_params_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; + + return (push8(init_tx_params_rel8->n_srs_initial, ppWritePackedMsg, end) && + push8(init_tx_params_rel8->initial_number_of_resource_blocks, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_initial_transmission_parameters(nfapi_ul_config_initial_transmission_parameters* init_tx_params, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return pack_tlv(NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &init_tx_params->initial_transmission_parameters_rel8, ppWritePackedMsg, end, &pack_ul_config_request_init_tx_params_rel8_value); +} + +static uint8_t pack_ul_config_request_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; + + return (push8(harq_info_rel10->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel10->delta_offset_harq, ppWritePackedMsg, end) && + push8(harq_info_rel10->ack_nack_mode, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; + + return (push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && + push8(harq_info_rel13->delta_offset_harq_2, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ulsch_harq_information(nfapi_ul_config_ulsch_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &harq_info->harq_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_harq_info_rel13_value)); +} + +static uint8_t pack_ul_config_request_ue_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; + + return ( push32(ue_info_rel8->handle, ppWritePackedMsg, end) && + push16(ue_info_rel8->rnti, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ue_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; + + return ( push8(ue_info_rel11->virtual_cell_id_enabled_flag, ppWritePackedMsg, end) && + push16(ue_info_rel11->npusch_identity, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_ue_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; + + return ( push8(ue_info_rel13->ue_type, ppWritePackedMsg, end) && + push8(ue_info_rel13->empty_symbols, ppWritePackedMsg, end) && + push16(ue_info_rel13->total_number_of_repetitions, ppWritePackedMsg, end) && + push16(ue_info_rel13->repetition_number, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_ue_information(nfapi_ul_config_ue_information* ue_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &ue_info->ue_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &ue_info->ue_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &ue_info->ue_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_ue_info_rel13_value)); +} + +static uint8_t pack_ul_config_request_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_rel10_tdd = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; + + return ( push8(harq_info_rel10_tdd->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel10_tdd->ack_nack_mode, ppWritePackedMsg, end) && + push8(harq_info_rel10_tdd->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_0, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_1, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_2, ppWritePackedMsg, end) && + push16(harq_info_rel10_tdd->n_pucch_1_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_rel8_fdd = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; + + return ( push16(harq_info_rel8_fdd->n_pucch_1_0, ppWritePackedMsg, end) && + push8(harq_info_rel8_fdd->harq_size, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_rel9_fdd = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; + + return ( push8(harq_info_rel9_fdd->harq_size, ppWritePackedMsg, end) && + push8(harq_info_rel9_fdd->ack_nack_mode, ppWritePackedMsg, end) && + push8(harq_info_rel9_fdd->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_0, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_1, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_2, ppWritePackedMsg, end) && + push16(harq_info_rel9_fdd->n_pucch_1_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel11_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; + + return ( push8(harq_info_rel11->num_ant_ports, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_0, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_1, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_2, ppWritePackedMsg, end) && + push16(harq_info_rel11->n_pucch_2_3, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_harq_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; + + return ( push16(harq_info_rel13->harq_size_2, ppWritePackedMsg, end) && + push8(harq_info_rel13->starting_prb, ppWritePackedMsg, end) && + push8(harq_info_rel13->n_prb, ppWritePackedMsg, end) && + push8(harq_info_rel13->cdm_index, ppWritePackedMsg, end) && + push8(harq_info_rel13->n_srs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_harq_information(nfapi_ul_config_harq_information* harq_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &harq_info->harq_information_rel10_tdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel10_tdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &harq_info->harq_information_rel8_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel8_fdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &harq_info->harq_information_rel9_fdd, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel9_fdd_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &harq_info->harq_information_rel11, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel11_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &harq_info->harq_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_harq_info_rel13_value)); + +} + +static uint8_t pack_ul_config_request_cqi_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; + + return ( push16(cqi_info_rel8->pucch_index, ppWritePackedMsg, end) && + push8(cqi_info_rel8->dl_cqi_pmi_size, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_cqi_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; + + return ( push8(cqi_info_rel10->number_of_pucch_resource, ppWritePackedMsg, end) && + push16(cqi_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); +} +static uint8_t pack_ul_config_request_cqi_info_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; + + return ( push8(cqi_info_rel13->csi_mode, ppWritePackedMsg, end) && + push16(cqi_info_rel13->dl_cqi_pmi_size_2, ppWritePackedMsg, end) && + push8(cqi_info_rel13->starting_prb, ppWritePackedMsg, end) && + push8(cqi_info_rel13->n_prb, ppWritePackedMsg, end) && + push8(cqi_info_rel13->cdm_index, ppWritePackedMsg, end) && + push8(cqi_info_rel13->n_srs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_cqi_information(nfapi_ul_config_cqi_information* cqi_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &cqi_info->cqi_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &cqi_info->cqi_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &cqi_info->cqi_information_rel13, ppWritePackedMsg, end, &pack_ul_config_request_cqi_info_rel13_value)); + +} + +static uint8_t pack_ul_config_request_sr_info_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; + return push16(sr_info_rel8->pucch_index, ppWritePackedMsg, end); +} +static uint8_t pack_ul_config_request_sr_info_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; + + return ( push8(sr_info_rel10->number_of_pucch_resources, ppWritePackedMsg, end) && + push16(sr_info_rel10->pucch_index_p1, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_sr_information(nfapi_ul_config_sr_information* sr_info, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &sr_info->sr_information_rel8, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &sr_info->sr_information_rel10, ppWritePackedMsg, end, &pack_ul_config_request_sr_info_rel10_value)); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; + + return (push32(srs_pdu_rel8->handle, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->size, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->srs_bandwidth, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->frequency_domain_position, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->srs_hopping_bandwidth, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->transmission_comb, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->i_srs, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->sounding_reference_cyclic_shift, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel10_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; + return push8(srs_pdu_rel10->antenna_port, ppWritePackedMsg, end); +} + +static uint8_t pack_ul_config_request_srs_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; + + return ( push8(srs_pdu_rel13->number_of_combs, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_nb_harq_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_pdu_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; + + return ( push8(nb_harq_pdu_rel13->harq_ack_resource, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_config_request_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; + + return (push8(nulsch_pdu_rel13->nulsch_format, ppWritePackedMsg, end) && + push32(nulsch_pdu_rel13->handle, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->size, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && + push8(nulsch_pdu_rel13->n_srs, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, ppWritePackedMsg, end) && + push16(nulsch_pdu_rel13->sf_idx, ppWritePackedMsg, end) && + pack_ul_config_request_ue_information(&(nulsch_pdu_rel13->ue_information), ppWritePackedMsg, end) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, ppWritePackedMsg, end, &pack_ul_config_request_nb_harq_rel13_value)); +} +static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; + + return ( push8(nrach_pdu_rel13->nprach_config_0, ppWritePackedMsg, end) && + push8(nrach_pdu_rel13->nprach_config_1, ppWritePackedMsg, end) && + push8(nrach_pdu_rel13->nprach_config_2, ppWritePackedMsg, end)); + +} + + + +static uint8_t pack_ul_tti_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_tti_request_number_of_pdus_t* value = (nfapi_nr_ul_tti_request_number_of_pdus_t*)tlv; + + if(!(push16(value->pdu_size, ppWritePackedMsg, end) && + push16(value->pdu_type, ppWritePackedMsg, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->pdu_type) + { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + { + if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + { + if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + { + if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + { + if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); + } + break; + } + + return 1; +} + +static uint8_t pack_ul_tti_groups_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_tti_request_number_of_groups_t* value = (nfapi_nr_ul_tti_request_number_of_groups_t*)tlv; + + if(!push8(value->n_ue, ppWritePackedMsg, end)) + return 0; + for(int i=0; in_ue;i++) + { + if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) + return 0; + } + return 1; +} + +static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; + + if(!(push8(value->number_of_pdus, ppWritePackedMsg, end) && + push8(value->rach_prach_frequency_resources, ppWritePackedMsg, end) && + push8(value->srs_present, ppWritePackedMsg, end))) + return 0; + + uint16_t i = 0; + for(i = 0; i < value->number_of_pdus; ++i) + { + nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: + { + if(!pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_pdu), ppWritePackedMsg, end)) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_harq_pdu.harq_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_harq_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_ri_information(&(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information), ppWritePackedMsg, end) && + pack_ul_config_request_ulsch_harq_information(&(pdu->ulsch_cqi_harq_ri_pdu.harq_information), ppWritePackedMsg, end) && + pack_ul_config_request_initial_transmission_parameters(&(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_pdu.cqi_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_sr_pdu.sr_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_harq_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_cqi_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_pdu.sr_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->uci_cqi_sr_harq_pdu.ue_information), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->uci_cqi_sr_harq_pdu.cqi_information), ppWritePackedMsg, end) && + pack_ul_config_request_sr_information(&(pdu->uci_cqi_sr_harq_pdu.sr_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->uci_cqi_sr_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &pdu->srs_pdu.srs_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel8_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &pdu->srs_pdu.srs_pdu_rel10, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel10_value) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &pdu->srs_pdu.srs_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_srs_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: + { + if(!(pack_ul_config_request_ue_information(&(pdu->harq_buffer_pdu.ue_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_csi_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->ulsch_uci_csi_pdu.csi_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->ulsch_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: + { + if(!(pack_ul_config_request_ulsch_pdu(&(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu), ppWritePackedMsg, end) && + pack_ul_config_request_cqi_information(&(pdu->ulsch_csi_uci_harq_pdu.csi_information), ppWritePackedMsg, end) && + pack_ul_config_request_harq_information(&(pdu->ulsch_csi_uci_harq_pdu.harq_information), ppWritePackedMsg, end))) + return 0; + } + break; + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &pdu->nulsch_pdu.nulsch_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nulsch_pdu_rel13_value))) + return 0; + } + break; + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &pdu->nrach_pdu.nrach_pdu_rel13, ppWritePackedMsg, end, &pack_ul_config_request_nrach_pdu_rel13_value))) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + + } + return 1; +} + + +static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && + push8(pNfapiMsg->n_pdus , ppWritePackedMsg, end) && + push8(pNfapiMsg->rach_present, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_group, ppWritePackedMsg, end) )) + return 0; + + for(int i=0; in_pdus; i++) + { + if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) + return 0; + } + + for(int i=0; in_group; i++) + { + if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) + return 0; + + } + + return 1; +} + + +static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, ppWritePackedMsg, end, &pack_ul_config_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)) ; +} + +static uint8_t pack_hi_dci0_hi_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; + + return ( push8(hi_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->hi_value, ppWritePackedMsg, end) && + push8(hi_pdu_rel8->i_phich, ppWritePackedMsg, end) && + push16(hi_pdu_rel8->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_hi_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; + + return ( push8(hi_pdu_rel10->flag_tb2, ppWritePackedMsg, end) && + push8(hi_pdu_rel10->hi_value_2, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel8_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; + + return ( push8(dci_pdu_rel8->dci_format, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cce_index, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->aggregation_level, ppWritePackedMsg, end) && + push16(dci_pdu_rel8->rnti, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->resource_block_start, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->number_of_resource_block, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->mcs_1, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cyclic_shift_2_for_drms, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->frequency_hopping_enabled_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->frequency_hopping_bits, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->new_data_indication_1, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->ue_tx_antenna_seleciton, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->tpc, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->cqi_csi_request, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->ul_index, ppWritePackedMsg, end) && + push8(dci_pdu_rel8->dl_assignment_index, ppWritePackedMsg, end) && + push32(dci_pdu_rel8->tpc_bitmap, ppWritePackedMsg, end) && + push16(dci_pdu_rel8->transmission_power, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel10_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; + + return ( push8(dci_pdu_rel10->cross_carrier_scheduling_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->carrier_indicator, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->size_of_cqi_csi_feild, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->srs_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->srs_request, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->resource_allocation_flag, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->resource_allocation_type, ppWritePackedMsg, end) && + push32(dci_pdu_rel10->resource_block_coding, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->mcs_2, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->new_data_indication_2, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->number_of_antenna_ports, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->tpmi, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->total_dci_length_including_padding, ppWritePackedMsg, end) && + push8(dci_pdu_rel10->n_ul_rb, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_dci_rel12_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; + + return ( push8(dci_pdu_rel12->pscch_resource, ppWritePackedMsg, end) && + push8(dci_pdu_rel12->time_resource_pattern, ppWritePackedMsg, end)); +} + +static uint8_t pack_hi_dci0_mpdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* mpdcch_dci_pdu_rel13 = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; + + return ( push8(mpdcch_dci_pdu_rel13->mpdcch_narrowband, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_prb_pairs, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->resource_block_assignment, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->mpdcch_transmission_type, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ecce_index, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->aggreagation_level, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->rnti_type, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ce_mode, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->drms_scrambling_init, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->initial_transmission_sf_io, ppWritePackedMsg, end) && + push16(mpdcch_dci_pdu_rel13->transmission_power, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dci_format, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->resource_block_start, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->pusch_repetition_levels, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->frequency_hopping_flag, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->new_data_indication, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->harq_process, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->redudency_version, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->tpc, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->csi_request, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->ul_inex, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dai_presence_flag, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dl_assignment_index, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->srs_request, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end) && + push32(mpdcch_dci_pdu_rel13->tcp_bitmap, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->total_dci_length_include_padding, ppWritePackedMsg, end) && + push8(mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end) && + pusharray16(mpdcch_dci_pdu_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_dci_pdu_rel13->number_of_tx_antenna_ports, ppWritePackedMsg, end)); + +} + +static uint8_t pack_hi_dci0_npdcch_dci_rel13_pdu_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* npdcch_dci_pdu_rel13 = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; + + return ( push8(npdcch_dci_pdu_rel13->ncce_index, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->aggregation_level, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->start_symbol, ppWritePackedMsg, end) && + push16(npdcch_dci_pdu_rel13->rnti, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->scrambling_reinitialization_batch_index, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->subcarrier_indication, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->resource_assignment, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->scheduling_delay, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->mcs, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->redudancy_version, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->repetition_number, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->new_data_indicator, ppWritePackedMsg, end) && + push8(npdcch_dci_pdu_rel13->dci_subframe_repetition_number, ppWritePackedMsg, end)); +} + + +static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; + + if(!(push16(value->sfnsf, ppWritePackedMsg, end) && + push8(value->number_of_dci, ppWritePackedMsg, end) && + push8(value->number_of_hi, ppWritePackedMsg, end))) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_dci + value->number_of_hi; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); + + if(push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_HI_DCI0_HI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_hi_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_hi_rel10_pdu_value))) + return 0; + } + break; + case NFAPI_HI_DCI0_DCI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, ppWritePackedMsg, end, pack_hi_dci0_dci_rel12_pdu_value))) + return 0; + } + break; + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, ppWritePackedMsg, end, pack_hi_dci0_dci_rel8_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, ppWritePackedMsg, end, pack_hi_dci0_dci_rel10_pdu_value) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, ppWritePackedMsg, end, pack_dl_config_epdcch_parameters_rel11_value))) + return 0; + } + break; + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_mpdcch_dci_rel13_pdu_value))) + return 0; + } + break; + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: + { + if(!(pack_tlv(NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, ppWritePackedMsg, end, pack_hi_dci0_npdcch_dci_rel13_pdu_value))) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + + } + + return 1; +} + +static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end))) + + return 0; + } + + return (push16(value->PDUType, ppWritePackedMsg, end) && + push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, ppWritePackedMsg, end)); + +} + +static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->numPdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumPdus; i++) + { + if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + return 1; + + +} + + + +static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, ppWritePackedMsg, end, &pack_hi_dci0_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +//pack_tx_data_pdu_list_value +static uint8_t pack_tx_data_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_pdu_t* value = (nfapi_nr_pdu_t*)tlv; + + if(!(push32(value->num_TLV, ppWritePackedMsg, end) && + push16(value->PDU_index, ppWritePackedMsg, end) && + push16(value->PDU_length, ppWritePackedMsg, end) + )) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_tlvs = value->num_TLV; + for(; i < total_number_of_tlvs; ++i) + { + + if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && + push16(value->TLVs[i].tag, ppWritePackedMsg, end))) + return 0; + + switch(value->TLVs[i].tag) + { + case 0: + { + if(!pusharray32(value->TLVs[i].value.direct, 16384, value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + break; + + } + + case 1: + { + if(!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length , value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + break; + + } + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); + break; + } + + } + } + return 1; +} + +static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_tx_request_body_t* value = (nfapi_tx_request_body_t*)tlv; + + if(push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(; i < total_number_of_pdus; ++i) + { + nfapi_tx_request_pdu_t* pdu = &(value->tx_pdu_list[i]); + + if(!(push16(pdu->pdu_length, ppWritePackedMsg, end) && + push16(pdu->pdu_index, ppWritePackedMsg, end))) + return 0; + + uint8_t j; + for(j = 0; j < pdu->num_segments; ++j) + { + // Use -1 as it is unbounded + // DJP - does not handle -1 + // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) + int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); + + if (pdu->segments[j].segment_length == 3) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, + pdu->segments[j].segment_data[0], + pdu->segments[j].segment_data[1], + pdu->segments[j].segment_data[2] + ); + } + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() segment_data:%p segment_length:%u pusharray8()=%d\n", __FUNCTION__, pdu->segments[j].segment_data, pdu->segments[j].segment_length, push_ret); + + if (push_ret == 0) + { + return 0; + } + } + } + + return 1; +} + +static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; + + if (!( + push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iNumber_of_PDUs; i++) + { + if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + +static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; + + int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + int y = pack_tlv(NFAPI_TX_REQUEST_BODY_TAG, &pNfapiMsg->tx_request_body, ppWritePackedMsg, end, &pack_tx_request_body_value); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() x:%d y:%d z:%d\n", __FUNCTION__, x, y, z); + + return x && y && z; +} + +static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv; + if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){ + return 0; + } + + uint8_t j; + uint16_t num = value->number_of_TLVs; + for(j = 0; j < num; ++j){ + if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){ + return 0; + } + } + return 1; +} + +static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; + int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return x && y && z; +} + +static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; + + int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return x && z; +} + +static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) ); +} + +static uint8_t unpack_rx_ue_information_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; + + return ( pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_bundling(nfapi_harq_indication_tdd_harq_data_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(data->value_0, ppWritePackedMsg, end) && + push8(data->value_1, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_multiplexing(nfapi_harq_indication_tdd_harq_data_multiplexing_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(data->value_0, ppWritePackedMsg, end) && + push8(data->value_1, ppWritePackedMsg, end) && + push8(data->value_2, ppWritePackedMsg, end) && + push8(data->value_3, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_tdd_harq_data_special_bundling(nfapi_harq_indication_tdd_harq_data_special_bundling_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(data->value_0, ppWritePackedMsg, end) ); +} + +static uint8_t pack_harq_indication_tdd_harq_data(nfapi_harq_indication_tdd_harq_data_t* data, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return ( push8(data->value_0, ppWritePackedMsg, end) ); +} + +static uint8_t pack_harq_indication_tdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel8_t* harq_indication_tdd_rel8 = (nfapi_harq_indication_tdd_rel8_t*)tlv; + + if(!(push8(harq_indication_tdd_rel8->mode, ppWritePackedMsg, end) && + push8(harq_indication_tdd_rel8->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t result = 0; + switch(harq_indication_tdd_rel8->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data_bundling(&harq_indication_tdd_rel8->harq_data.bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data_multiplexing(&harq_indication_tdd_rel8->harq_data.multiplex, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel8->harq_data.special_bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = 1; + break; + default: + // err.... + break; + } + + return result; + +} + +static uint8_t pack_harq_indication_tdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel9_t* harq_indication_tdd_rel9 = (nfapi_harq_indication_tdd_rel9_t*)tlv; + + if(!(push8(harq_indication_tdd_rel9->mode, ppWritePackedMsg, end) && + push8(harq_indication_tdd_rel9->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t idx; + for(idx = 0; idx < harq_indication_tdd_rel9->number_of_ack_nack; ++idx) + { + uint8_t result = 0; + + switch(harq_indication_tdd_rel9->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data(&(harq_indication_tdd_rel9->harq_data[idx].bundling), ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].multiplex, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel9->harq_data[idx].special_bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].channel_selection, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel9->harq_data[idx].format_3, ppWritePackedMsg, end); + break; + default: + // err.... + break; + } + + if(result == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_harq_indication_tdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel13_t* harq_indication_tdd_rel13 = (nfapi_harq_indication_tdd_rel13_t*)tlv; + + if(!(push8(harq_indication_tdd_rel13->mode, ppWritePackedMsg, end) && + push16(harq_indication_tdd_rel13->number_of_ack_nack, ppWritePackedMsg, end))) + return 0; + + uint8_t idx; + for(idx = 0; idx < harq_indication_tdd_rel13->number_of_ack_nack; ++idx) + { + uint8_t result = 0; + switch(harq_indication_tdd_rel13->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].multiplex, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = pack_harq_indication_tdd_harq_data_special_bundling(&harq_indication_tdd_rel13->harq_data[idx].special_bundling, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].channel_selection, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_3, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_4, ppWritePackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: + result = pack_harq_indication_tdd_harq_data(&harq_indication_tdd_rel13->harq_data[idx].format_5, ppWritePackedMsg, end); + break; + default: + // err.... + break; + } + + if(result == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_harq_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel8_t* harq_indication_fdd_rel8 = (nfapi_harq_indication_fdd_rel8_t*)tlv; + + return ( push8(harq_indication_fdd_rel8->harq_tb1, ppWritePackedMsg, end) && + push8(harq_indication_fdd_rel8->harq_tb2, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel9_t* harq_indication_fdd_rel9 = (nfapi_harq_indication_fdd_rel9_t*)tlv; + + return ( push8(harq_indication_fdd_rel9->mode, ppWritePackedMsg, end) && + push8(harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end) && + pusharray8(harq_indication_fdd_rel9->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, harq_indication_fdd_rel9->number_of_ack_nack, ppWritePackedMsg, end)); +} + +static uint8_t pack_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel13_t* harq_indication_fdd_rel13 = (nfapi_harq_indication_fdd_rel13_t*)tlv; + + return ( push8(harq_indication_fdd_rel13->mode, ppWritePackedMsg, end) && + push16(harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end) && + pusharray8(harq_indication_fdd_rel13->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, harq_indication_fdd_rel13->number_of_ack_nack, ppWritePackedMsg, end)); +} + +static uint8_t pack_ul_cqi_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; + + return ( push8(value->ul_cqi, ppWritePackedMsg, end) && + push8(value->channel, ppWritePackedMsg, end)); + +} + +static uint8_t pack_harq_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; + + if(push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_harqs; + for(; i < total_number_of_pdus; ++i) + { + nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, ppWritePackedMsg, end, pack_harq_indication_tdd_rel8_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, ppWritePackedMsg, end, pack_harq_indication_tdd_rel9_value) && + pack_tlv(NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, ppWritePackedMsg, end, pack_harq_indication_tdd_rel13_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, ppWritePackedMsg, end, pack_harq_indication_fdd_rel8_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, ppWritePackedMsg, end, pack_harq_indication_fdd_rel9_value) && + pack_tlv(NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_harq_indication_fdd_rel13_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, ppWritePackedMsg, end, pack_harq_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_crc_indication_rel8_body(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_crc_indication_rel8_t* crc_indication_rel8 = (nfapi_crc_indication_rel8_t*)tlv; + + return ( push8(crc_indication_rel8->crc_flag, ppWritePackedMsg, end) ); +} + +static uint8_t pack_crc_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; + + if(push16(value->number_of_crcs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_crcs; + for(; i < total_number_of_pdus; ++i) + { + nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, ppWritePackedMsg, end, pack_crc_indication_rel8_body))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + return 1; +} + +static uint8_t pack_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, ppWritePackedMsg, end, &pack_crc_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} +static uint8_t pack_rx_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; + + return ( push16(value->length, ppWritePackedMsg, end) && + push16(value->offset, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end)); +} +static uint8_t pack_rx_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; + + return ( push16(value->timing_advance_r9, ppWritePackedMsg, end)); +} + +static uint8_t pack_rx_ulsch_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; + + //printf("RX ULSCH BODY\n"); + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + // need to calculate the data offset's. + uint16_t i = 0; + uint16_t offset = 2; // taking into account the number_of_pdus + uint16_t total_number_of_pdus = value->number_of_pdus; + //printf("ULSCH:pdus:%d\n", total_number_of_pdus); + + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) + { + //printf("NFAPI_RX_UE_INFORMATION_TAG\n"); + offset += 4 + 6; + } + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) + { + //printf("NFAPI_RX_INDICATION_REL8_TAG\n"); + offset += 4 + 7; + } + + if(pdu->rx_indication_rel9.tl.tag == NFAPI_RX_INDICATION_REL9_TAG) + { + //printf("NFAPI_RX_INDICATION_REL9_TAG\n"); + offset += 4 + 2; + } + } + + // Now update the structure to include the offset + for(i =0; i < total_number_of_pdus; ++i) + { + nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) + { + if(pdu->rx_indication_rel8.offset == 1) + { + pdu->rx_indication_rel8.offset = offset; + offset += pdu->rx_indication_rel8.length; + } + } + } + + // Write out the pdu + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_RX_INDICATION_REL8_TAG, &pdu->rx_indication_rel8, ppWritePackedMsg, end, pack_rx_indication_rel8_value) && + pack_tlv(NFAPI_RX_INDICATION_REL9_TAG, &pdu->rx_indication_rel9, ppWritePackedMsg, end, pack_rx_indication_rel9_value))) + return 0; + } + + // Write out the pdu data + for(i = 0; i < total_number_of_pdus; ++i) + { + uint16_t length = 0; + nfapi_rx_indication_pdu_t* pdu = &(value->rx_pdu_list[i]); + + if(pdu->rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) + { + length = pdu->rx_indication_rel8.length; + } + + if( pusharray8(value->rx_pdu_list[i].data, length, length, ppWritePackedMsg, end) == 0) + return 0; + } + return 1; +} + + +static uint8_t pack_rx_ulsch_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, ppWritePackedMsg, end, pack_rx_ulsch_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_preamble_pdu_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel8_t* preamble_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; + + return ( push16(preamble_rel8->rnti, ppWritePackedMsg, end) && + push8(preamble_rel8->preamble, ppWritePackedMsg, end) && + push16(preamble_rel8->timing_advance, ppWritePackedMsg, end)); +} +static uint8_t pack_preamble_pdu_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel9_t* preamble_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; + + return ( push16(preamble_rel9->timing_advance_r9, ppWritePackedMsg, end) ); +} +static uint8_t pack_preamble_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel13_t* preamble_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; + + return ( push8(preamble_rel13->rach_resource_type, ppWritePackedMsg, end) ); +} + +static uint8_t pack_rach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; + + if( push16(value->number_of_preambles, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_preambles; + for(; i < total_number_of_pdus; ++i) + { + nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, ppWritePackedMsg, end, pack_preamble_pdu_rel8_value) && + pack_tlv(NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, ppWritePackedMsg, end, pack_preamble_pdu_rel9_value) && + pack_tlv(NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, ppWritePackedMsg, end, pack_preamble_pdu_rel13_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, ppWritePackedMsg, end, pack_rach_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel8_t* srs_pdu_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; + + return ( push16(srs_pdu_rel8->doppler_estimation, ppWritePackedMsg, end) && + push16(srs_pdu_rel8->timing_advance, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end) && + push8(srs_pdu_rel8->rb_start, ppWritePackedMsg, end) && + pusharray8(srs_pdu_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_rel8->number_of_resource_blocks, ppWritePackedMsg, end)); +} + +static uint8_t pack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel9_t* srs_pdu_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; + + return ( push16(srs_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end) ); +} + +static uint8_t pack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_ttd_rel10_t* srs_pdu_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; + + return ( push8(srs_pdu_rel10->uppts_symbol, ppWritePackedMsg, end) ); + +} + +static uint8_t pack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel11_t* srs_pdu_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; + + return ( push16(srs_pdu_rel11->ul_rtoa, ppWritePackedMsg, end) ) ; +} + +static uint8_t pack_tdd_channel_measurement_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; + + if(!(push8(value->num_prb_per_subband, ppWritePackedMsg, end) && + push8(value->number_of_subbands, ppWritePackedMsg, end) && + push8(value->num_atennas, ppWritePackedMsg, end))) + return 0; + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) + { + if(!(push8(value->subands[idx].subband_index, ppWritePackedMsg, end) && + pusharray16(value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, ppWritePackedMsg, end))) + return 0; + } + + return 1; +} + +static uint8_t pack_srs_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_srs_indication_body_t *value = (nfapi_srs_indication_body_t*)tlv; + + if( push8(value->number_of_ues, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_ues; + for(; i < total_number_of_pdus; ++i) + { + nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, &pack_rx_ue_information_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel8_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel9_value) && + pack_tlv(NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, ppWritePackedMsg, end, &pack_srs_indication_tdd_rel10_value) && + pack_tlv(NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, ppWritePackedMsg, end, &pack_srs_indication_fdd_rel11_value) && + pack_tlv(NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, ppWritePackedMsg, end, &pack_tdd_channel_measurement_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, ppWritePackedMsg, end, &pack_srs_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} + +static uint8_t pack_sr_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; + + if(push16(value->number_of_srs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_srs; + for(; i < total_number_of_pdus; ++i) + { + nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + return 1; +} + +static uint8_t pack_sr_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, ppWritePackedMsg, end, &pack_sr_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} + +static uint8_t pack_cqi_indication_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; + + return ( push16(cqi_pdu_rel8->length, ppWritePackedMsg, end) && + push16(cqi_pdu_rel8->data_offset, ppWritePackedMsg, end) && + push8(cqi_pdu_rel8->ul_cqi, ppWritePackedMsg, end) && + push8(cqi_pdu_rel8->ri, ppWritePackedMsg, end) && + push16(cqi_pdu_rel8->timing_advance, ppWritePackedMsg, end)); +} + +static uint8_t pack_cqi_indication_rel9_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; + + return ( push16(cqi_pdu_rel9->length, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->data_offset, ppWritePackedMsg, end) && + push8(cqi_pdu_rel9->ul_cqi, ppWritePackedMsg, end) && + push8(cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && + pusharray8(cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->timing_advance, ppWritePackedMsg, end) && + push16(cqi_pdu_rel9->timing_advance_r9, ppWritePackedMsg, end)); +} + +static uint8_t pack_cqi_indication_body_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; + + if( push16(value->number_of_cqis, ppWritePackedMsg, end) == 0) + return 0; + + // need to calculate the data offset's. This very bittle due the hardcoding + // of the sizes. can not use the sizeof as we have an array for the Rel9 + // info + uint16_t i = 0; + uint16_t offset = 2; // taking into account the number_of_cqis + uint16_t total_number_of_pdus = value->number_of_cqis; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + + offset += 2; // for the instance length + + if(pdu->rx_ue_information.tl.tag == NFAPI_RX_UE_INFORMATION_TAG) + { + offset += 4 + 6; // sizeof(nfapi_rx_ue_information) - sizeof(nfapi_tl_t) + } + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) + { + offset += 4 + 8; + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) + { + offset += 4 + 10 + pdu->cqi_indication_rel9.number_of_cc_reported; + } + + if(pdu->ul_cqi_information.tl.tag == NFAPI_UL_CQI_INFORMATION_TAG) + { + offset += 4 + 2; + } + } + + // Now update the structure to include the offset + for(i =0; i < total_number_of_pdus; ++i) + { + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) + { + if(pdu->cqi_indication_rel8.data_offset == 1) + { + pdu->cqi_indication_rel8.data_offset = offset; + offset += pdu->cqi_indication_rel8.length; + } + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) + { + if(pdu->cqi_indication_rel9.data_offset == 1) + { + pdu->cqi_indication_rel9.data_offset = offset; + offset += pdu->cqi_indication_rel9.length; + } + } + + } + + // Write out the cqi information + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end ,pack_rx_ue_information_value) && + pack_tlv(NFAPI_CQI_INDICATION_REL8_TAG, &pdu->cqi_indication_rel8, ppWritePackedMsg, end, pack_cqi_indication_rel8_value) && + pack_tlv(NFAPI_CQI_INDICATION_REL9_TAG, &pdu->cqi_indication_rel9, ppWritePackedMsg, end, pack_cqi_indication_rel9_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + + } + + // Write out the cqi raw data + for(i = 0; i < total_number_of_pdus; ++i) + { + uint16_t length = 0; + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + + if(pdu->cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) + { + length = pdu->cqi_indication_rel8.length; + } + + if(pdu->cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) + { + length = pdu->cqi_indication_rel9.length; + } + + if( pusharray8(value->cqi_raw_pdu_list[i].pdu, NFAPI_CQI_RAW_MAX_LEN, length, ppWritePackedMsg, end) == 0) + return 0; + } + + return 1; +} + +static uint8_t pack_cqi_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, ppWritePackedMsg, end, pack_cqi_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} + +static uint8_t pack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->mp_cca, ppWritePackedMsg, end) && + push32(value->n_cca, ppWritePackedMsg, end) && + push32(value->offset, ppWritePackedMsg, end) && + push32(value->lte_txop_sf, ppWritePackedMsg, end) && + push16(value->txop_sfn_sf_end, ppWritePackedMsg, end) && + push32(value->lbt_mode, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->offset, ppWritePackedMsg, end) && + push16(value->sfn_sf_end, ppWritePackedMsg, end) && + push32(value->lbt_mode, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(; i < total_number_of_pdus; ++i) + { + nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); + + if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + if( push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: + { + if( pack_tlv(NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_req_pdu_rel13_value) == 0) + return 0; + } + break; + case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: + { + if(pack_tlv(NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_req_pdu_rel13_value) == 0) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + +static uint8_t pack_lbt_pdsch_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->result, ppWritePackedMsg, end) && + push32(value->lte_txop_symbols, ppWritePackedMsg, end) && + push32(value->initial_partial_sf, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_drs_rsp_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; + + return ( push32(value->handle, ppWritePackedMsg, end) && + push32(value->result, ppWritePackedMsg, end)); +} + +static uint8_t pack_lbt_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, ppWritePackedMsg, end, &pack_lbt_dl_config_request_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_lbt_dl_config_indication_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; + + if( push16(value->number_of_pdus, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(; i < total_number_of_pdus; ++i) + { + nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); + + if( push8(pdu->pdu_type, ppWritePackedMsg, end) == 0) + return 0; + + // Put a 0 size in and then determine the size after the pdu + // has been writen and write the calculated size + uint8_t* pWritePackedMsgPduSize = *ppWritePackedMsg; + pdu->pdu_size = 0; + + if(push8(pdu->pdu_size, ppWritePackedMsg, end) == 0) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: + { + if( pack_tlv(NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_pdsch_rsp_pdu_rel13_value) == 0) + return 0; + } + break; + case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: + { + if( pack_tlv(NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, ppWritePackedMsg, end, pack_lbt_drs_rsp_pdu_rel13_value) == 0) + return 0; + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + + // add 1 for the pdu_type. The delta will include the pdu_size + pdu->pdu_size = 1 + (*ppWritePackedMsg - pWritePackedMsgPduSize); + push8(pdu->pdu_size, &pWritePackedMsgPduSize, end); + } + + return 1; +} + +static uint8_t pack_lbt_dl_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, ppWritePackedMsg, end, &pack_lbt_dl_config_indication_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nb_harq_indication_fdd_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nb_harq_indication_fdd_rel13_t* nb_harq_indication_fdd_rel13 = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; + + return ( push8(nb_harq_indication_fdd_rel13->harq_tb1, ppWritePackedMsg, end) ); +} + +static uint8_t pack_nb_harq_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; + + if( push16(value->number_of_harqs, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_harqs = value->number_of_harqs; + for(; i < total_number_of_harqs; ++i) + { + nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); + + uint8_t* instance_length_p = *ppWritePackedMsg; + if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + return 0; + + if(!(pack_tlv(NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, ppWritePackedMsg, end, pack_rx_ue_information_value) && + pack_tlv(NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, ppWritePackedMsg, end, pack_nb_harq_indication_fdd_rel13_value) && + pack_tlv(NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, ppWritePackedMsg, end, pack_ul_cqi_information_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + push16(instance_length, &instance_length_p, end); + } + + return 1; +} + + +static uint8_t pack_nb_harq_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, ppWritePackedMsg, end, &pack_nb_harq_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nrach_indication_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nrach_indication_pdu_rel13_t* nrach_indication_fdd_rel13 = (nfapi_nrach_indication_pdu_rel13_t*)tlv; + + return ( push16(nrach_indication_fdd_rel13->rnti, ppWritePackedMsg, end) && + push8(nrach_indication_fdd_rel13->initial_sc, ppWritePackedMsg, end) && + push16(nrach_indication_fdd_rel13->timing_advance, ppWritePackedMsg, end) && + push8(nrach_indication_fdd_rel13->nrach_ce_level, ppWritePackedMsg, end)); +} + + +static uint8_t pack_nrach_indication_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; + + if( push8(value->number_of_initial_scs_detected, ppWritePackedMsg, end) == 0) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_initial_scs_detected = value->number_of_initial_scs_detected; + for(; i < total_number_of_initial_scs_detected; ++i) + { + nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); + + //uint8_t* instance_length_p = *ppWritePackedMsg; + //if(!push16(pdu->instance_length, ppWritePackedMsg, end)) + // return 0; + + if(!(pack_tlv(NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, ppWritePackedMsg, end, pack_nrach_indication_rel13_value))) + return 0; + + // calculate the instance length subtracting the size of the instance + // length feild + //uint16_t instance_length = *ppWritePackedMsg - instance_length_p - 2; + //push16(instance_length, &instance_length_p, end); + } + + return 1; +} + +static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; + + return ( push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, ppWritePackedMsg, end, &pack_nrach_indication_body_value) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; + + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; + + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_sf, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; + + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; + + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; + + return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_config_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->hi_dci0_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_config_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_config_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->hi_dci0_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_config_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_config_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->hi_dci0_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + +static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; + + return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && + push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + +//NR UPLINK indication function packing + +//RX DATA INDICATION + +static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push16(value->pdu_length, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + + +static uint8_t pack_nr_rx_data_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rx_data_indication_body(pNfapiMsg->pdu_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t pack_nr_crc_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->harq_id, ppWritePackedMsg, end) && + push8(value->tb_crc_status, ppWritePackedMsg, end) && + push16(value->num_cb, ppWritePackedMsg, end) && + //pusharray8(value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, ppWritePackedMsg, end) && //length is ceil(NumCb/8) + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + return 1; +} + +static uint8_t pack_nr_crc_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_crcs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!pack_nr_crc_indication_body(pNfapiMsg->crc_list,ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t pack_nr_srs_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push8(value->num_symbols, ppWritePackedMsg, end) && + push8(value->wide_band_snr, ppWritePackedMsg, end) && + push8(value->num_reported_symbols, ppWritePackedMsg, end) && + push8(value->reported_symbol_list->num_rbs, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(push8(value->reported_symbol_list->rb_list->rb_snr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_srs_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_srs_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +//RACH INDICATION + +static uint8_t pack_nr_rach_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(push16(value->phy_cell_id, ppWritePackedMsg, end) && + push8(value->symbol_index, ppWritePackedMsg, end) && + push8(value->slot_index, ppWritePackedMsg, end) && + push8(value->freq_index, ppWritePackedMsg, end) && + push8(value->avg_rssi, ppWritePackedMsg, end) && + push8(value->avg_snr, ppWritePackedMsg, end) && + push8(value->num_preamble, ppWritePackedMsg, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(push8(value->preamble_list->preamble_index, ppWritePackedMsg, end) && + push16(value->preamble_list->timing_advance, ppWritePackedMsg, end) && + push32(value->preamble_list->preamble_pwr, ppWritePackedMsg, end) + )) + return 0; + } + return 1; +} + +static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!pack_nr_rach_indication_body(&(pNfapiMsg->pdu_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + +//UCI INDICATION + +static uint8_t pack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr->sr_indication, ppWritePackedMsg, end) && + push8(value->sr->sr_confidence_level, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq->num_harq, ppWritePackedMsg, end) && + push8(value->harq->harq_confidence_level, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iharq->num_harq;i++) + { + if(!(push8(value->harq->harq_list[i].harq_value, ppWritePackedMsg, end) + )) + return 0; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(push8(value->pduBitmap, ppWritePackedMsg, end) && + push32(value->handle, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push8(value->pucch_format, ppWritePackedMsg, end) && + push8(value->ul_cqi, ppWritePackedMsg, end) && + push16(value->timing_advance, ppWritePackedMsg, end) && + push16(value->rssi, ppWritePackedMsg, end) + )) + return 0; + + if (value->pduBitmap & 0x01) { //SR + if(!(push8(value->sr.sr_bit_len, ppWritePackedMsg, end) && + pusharray8(value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(push8(value->harq.harq_crc, ppWritePackedMsg, end) && + push8(value->harq.harq_bit_len, ppWritePackedMsg, end) && + pusharray8(value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(push8(value->csi_part1.csi_part1_crc, ppWritePackedMsg, end) && + push8(value->csi_part1.csi_part1_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(push8(value->csi_part2.csi_part2_crc, ppWritePackedMsg, end) && + push8(value->csi_part2.csi_part2_bit_len, ppWritePackedMsg, end) && + pusharray8(value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, ppWritePackedMsg, end) + )) + return 0; + } + + return 1; +} + +static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(push16(value->pdu_type, ppWritePackedMsg, end) && + push16(value->pdu_size, ppWritePackedMsg, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16(pNfapiMsg->slot , ppWritePackedMsg, end) && + push16(pNfapiMsg->num_ucis, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + +// Main pack function - public + +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) +{ + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; + + if (pMessageBuf == NULL || pPackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + printf("result of pack dl_tti_req is %d. \n",result); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + result = pack_nr_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + result = pack_nr_uci_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: + { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->pack_p7_vendor_extension) + { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + if(result == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } + else + { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; + + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; + + if(1) + { + //quick test + if(pMessageHeader->message_length != packedMsgLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } + + return (packedMsgLen); +} + +int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) +{ + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; + + if (pMessageBuf == NULL || pPackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) + { + case NFAPI_DL_CONFIG_REQUEST: + result = pack_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UL_CONFIG_REQUEST: + result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_TX_REQUEST: + result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_HI_DCI0_REQUEST: + result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_HARQ_INDICATION: + result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_CRC_INDICATION: + result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_ULSCH_INDICATION: + result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RACH_INDICATION: + result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SRS_INDICATION: + result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_SR_INDICATION: + result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_CQI_INDICATION: + result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_INDICATION: + result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NB_HARQ_INDICATION: + result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NRACH_INDICATION: + result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_DL_NODE_SYNC: + result = pack_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UL_NODE_SYNC: + result = pack_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: + { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->pack_p7_vendor_extension) + { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + if(result == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } + else + { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; + + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; + + if(1) + { + //quick test + if(pMessageHeader->message_length != packedMsgLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } + + return (packedMsgLen); +} + +// Unpack routines +// NR: +static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; + + return( + pull16(ppReadPackedMsg, &value->bwp_size, end) && + pull16(ppReadPackedMsg, &value->bwp_start, end) && + + pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && + + pull16(ppReadPackedMsg, &value->start_rb, end) && + pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && + + pull8(ppReadPackedMsg, &value->csi_type, end) && + pull8(ppReadPackedMsg, &value->row, end) && + + pull16(ppReadPackedMsg, &value->freq_domain, end) && + pull8(ppReadPackedMsg, &value->symb_l0, end) && + + pull8(ppReadPackedMsg, &value->symb_l1, end) && + pull8(ppReadPackedMsg, &value->cdm_type, end) && + + pull8(ppReadPackedMsg, &value->freq_density, end) && + pull16(ppReadPackedMsg, &value->scramb_id, end) && + + pull8(ppReadPackedMsg, &value->power_control_offset, end) && + pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) + ); + +} + + +static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && + + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && + + pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && + + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, value->dci_pdu[i].PayloadSizeBits, value->dci_pdu[i].PayloadSizeBits, end))) + + return 0; + } + + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->BWPSize, end) && + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && + + pull8(ppReadPackedMsg, &value->RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->CoreSetType, end) && + pull16(ppReadPackedMsg, &value->ShiftIndex, end) && + + pull8(ppReadPackedMsg, &value->precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->numDlDci, end)); + +} + + +static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; + + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->pduBitmap, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->pduIndex, end) && + pull16(ppReadPackedMsg, &value->BWPSize, end) && + + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && + + pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && + + pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && + pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && + pull16(ppReadPackedMsg, &value->dataScramblingId, end) && + pull8(ppReadPackedMsg, &value->nrOfLayers, end) && + + pull8(ppReadPackedMsg, &value->transmissionScheme, end) && + pull8(ppReadPackedMsg, &value->refPoint, end) && + pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && + pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && + + pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && + pull8(ppReadPackedMsg, &value->SCID, end) && + pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && + pull16(ppReadPackedMsg, &value->dmrsPorts, end) && + + pull8(ppReadPackedMsg, &value->resourceAlloc, end) && + pull16(ppReadPackedMsg, &value->rbStart, end) && + pull16(ppReadPackedMsg, &value->rbSize, end) && + + pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && + pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && + + pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSReOffset, end) + ); + +} + + +static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + printf("ssb received and unpacked. \n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; + + return( + pull16(ppReadPackedMsg, &value->PhysCellId, end) && + pull8(ppReadPackedMsg, &value->BetaPss, end) && + pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && + pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && + pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && + pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && + pull32(ppReadPackedMsg, &value->bchPayload, end) + // TODO: pack precoding_and_beamforming too + ); + +} + + +// LTE: +static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel8_t* dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->dci_format, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->cce_idx, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->aggregation_level, end) && + pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &dci_dl_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_1, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->mcs_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->redundancy_version_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->new_data_indicator_2, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->harq_process, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpmi, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->pmi, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->precoding_information, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->tpc, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_assignment_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->ngap, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->transport_block_size_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->downlink_power_offset, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->allocate_prach_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->preamble_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->prach_mask_index, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel8->rnti_type, end) && + pull16(ppReadPackedMsg, &dci_dl_pdu_rel8->transmission_power, end)); + +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel9_t* dci_dl_pdu_rel9 = (nfapi_dl_config_dci_dl_pdu_rel9_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->mcch_change_notification, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel9->scrambling_identity, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel10_t* dci_dl_pdu_rel10 = (nfapi_dl_config_dci_dl_pdu_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->cross_carrier_scheduling_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->carrier_indicator, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->srs_request, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->antenna_ports_scrambling_and_layers, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel10->n_dl_rb, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel11_t* dci_dl_pdu_rel11 = (nfapi_dl_config_dci_dl_pdu_rel11_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->harq_ack_resource_offset, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel11->pdsch_re_mapping_quasi_co_location_indicator, end)); +} + +static uint8_t unpack_dl_config_dci_dl_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel12_t* dci_dl_pdu_rel12 = (nfapi_dl_config_dci_dl_pdu_rel12_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->primary_cell_type, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->ul_dl_configuration_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel12->number_ul_dl_configurations, end) && + pullarray8(ppReadPackedMsg, dci_dl_pdu_rel12->ul_dl_configuration_indication, NFAPI_MAX_UL_DL_CONFIGURATIONS, dci_dl_pdu_rel12->number_ul_dl_configurations, end)); +} + +static uint8_t unpack_tpm_value(uint8_t **ppReadPackedMsg, nfapi_dl_config_dci_dl_tpm_t *value, uint8_t *end) +{ + if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && + pull8(ppReadPackedMsg, &value->number_of_subbands, end) && + pull8(ppReadPackedMsg, &value->num_antennas, end))) + return 0; + + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) + { + nfapi_dl_config_dci_dl_tpm_subband_info_t* subband_info = &(value->subband_info[idx]); + + if(!(pull8(ppReadPackedMsg, &subband_info->subband_index, end) && + pull8(ppReadPackedMsg, &subband_info->scheduled_ues, end))) + return 0; + + uint8_t antenna_idx = 0; + uint8_t scheduled_ue_idx = 0; + + for(antenna_idx = 0; antenna_idx < value->num_antennas; ++antenna_idx) + { + for(scheduled_ue_idx = 0; scheduled_ue_idx < subband_info->scheduled_ues; ++scheduled_ue_idx) + { + if(!pull16(ppReadPackedMsg, &(subband_info->precoding_value[antenna_idx][scheduled_ue_idx]), end)) + return 0; + } + } + + } + + + return 1; + +} + + +static uint8_t unpack_dl_config_dci_dl_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dci_dl_pdu_rel13_t* dci_dl_pdu_rel13 = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; + + // If the length is greater than 5 then the TPM struct flag and possiably the TPM structure have been + // added + uint8_t tpm_struct_flag_present = dci_dl_pdu_rel13->tl.length > 5; + dci_dl_pdu_rel13->tpm_struct_flag = 0; + + return (pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_flag, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->laa_end_partial_sf_configuration, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->initial_lbt_sf, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->codebook_size_determination, end) && + pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->drms_table_flag, end) && + ( (tpm_struct_flag_present == 1) ? pull8(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm_struct_flag, end) : 1) && + ( (tpm_struct_flag_present == 1 && dci_dl_pdu_rel13->tpm_struct_flag == 1) ? unpack_tpm_value(ppReadPackedMsg, &dci_dl_pdu_rel13->tpm, end) : 1)); + +} + +static uint8_t unpack_dl_config_bch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_bch_pdu_rel8_t* bch_pdu_rel8 = (nfapi_dl_config_bch_pdu_rel8_t*)tlv; + + return ( pull16(ppReadPackedMsg, &bch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&bch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &bch_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_dl_config_mch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_mch_pdu_rel8_t* mch_pdu_rel8 = (nfapi_dl_config_mch_pdu_rel8_t*)tlv; + + return (pull16(ppReadPackedMsg, &mch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&mch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &mch_pdu_rel8->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &mch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &mch_pdu_rel8->modulation, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->transmission_power, end) && + pull16(ppReadPackedMsg, &mch_pdu_rel8->mbsfn_area_id, end)); +} + +static uint8_t unpack_dl_config_dlsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel8_t* dlsch_pdu_rel8 = (nfapi_dl_config_dlsch_pdu_rel8_t*)tlv; + + if (!(pull16(ppReadPackedMsg, &dlsch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&dlsch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &dlsch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->modulation, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_blocks, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_scheme, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_layers, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->number_of_subbands, end) && + pullarray8(ppReadPackedMsg, dlsch_pdu_rel8->codebook_index, NFAPI_MAX_NUM_SUBBANDS, dlsch_pdu_rel8->number_of_subbands, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ue_category_capacity, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->pa, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->delta_power_offset_index, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->ngap, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->nprb, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->transmission_mode, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_prb_per_subband, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->num_bf_vector, end))) + return 0; + + uint16_t j = 0; + for(j = 0; j < dlsch_pdu_rel8->num_bf_vector; ++j) + { + if(!(pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].subband_index, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel8->bf_vector[j].num_antennas, end) && + pullarray16(ppReadPackedMsg, dlsch_pdu_rel8->bf_vector[j].bf_value, NFAPI_MAX_NUM_ANTENNAS, dlsch_pdu_rel8->bf_vector[j].num_antennas, end))) + return 0; + } + return 1; +} +static uint8_t unpack_dl_config_dlsch_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel9_t* dlsch_pdu_rel9 = (nfapi_dl_config_dlsch_pdu_rel9_t*)tlv; + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel9->nscid, end) ); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel10_t* dlsch_pdu_rel10 = (nfapi_dl_config_dlsch_pdu_rel10_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_resource_config_r10, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && + pullarray8(ppReadPackedMsg, dlsch_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, dlsch_pdu_rel10->csi_rs_number_nzp_configuration, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel10->pdsch_start, end)) ; +} +static uint8_t unpack_dl_config_dlsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel11_t* dlsch_pdu_rel11 = (nfapi_dl_config_dlsch_pdu_rel11_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel11->drms_config_flag, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel11->drms_scrambling, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->csi_config_flag, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel11->csi_scrambling, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_flag, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_atenna_ports, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel11->pdsch_re_mapping_freq_shift, end)); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel12_t* dlsch_pdu_rel12 = (nfapi_dl_config_dlsch_pdu_rel12_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel12->altcqi_table_r12, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel12->maxlayers, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel12->n_dl_harq, end)); +} +static uint8_t unpack_dl_config_dlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_dlsch_pdu_rel13_t* dlsch_pdu_rel13 = (nfapi_dl_config_dlsch_pdu_rel13_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dlsch_pdu_rel13->dwpts_symbols, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->initial_lbt_sf, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->ue_type, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->pdsch_payload_type, end) && + pull16(ppReadPackedMsg, &dlsch_pdu_rel13->initial_transmission_sf_io, end) && + pull8(ppReadPackedMsg, &dlsch_pdu_rel13->drms_table_flag, end)); +} + +static uint8_t unpack_dl_config_pch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_pch_pdu_rel8_t* pch_pdu_rel8 = (nfapi_dl_config_pch_pdu_rel8_t*)tlv; + + return ( pull16(ppReadPackedMsg, &pch_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&pch_pdu_rel8->pdu_index, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel8->p_rnti, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->resource_allocation_type, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->virtual_resource_block_assignment_flag, end) && + pull32(ppReadPackedMsg, &pch_pdu_rel8->resource_block_coding, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->mcs, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_transport_blocks, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->transport_block_to_codeword_swap_flag, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->transmission_scheme, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->number_of_layers, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->codebook_index, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->ue_category_capacity, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->pa, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel8->transmission_power, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->nprb, end) && + pull8(ppReadPackedMsg, &pch_pdu_rel8->ngap, end)); +} +static uint8_t unpack_dl_config_pch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_pch_pdu_rel13_t* pch_pdu_rel13 = (nfapi_dl_config_pch_pdu_rel13_t*)tlv; + + return ( pull8(ppReadPackedMsg, &pch_pdu_rel13->ue_mode, end) && + pull16(ppReadPackedMsg, &pch_pdu_rel13->initial_transmission_sf_io, end)); +} + +static uint8_t unpack_dl_config_prs_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_prs_pdu_rel9_t* prs_pdu_rel9 = (nfapi_dl_config_prs_pdu_rel9_t*)tlv; + + return ( pull16(ppReadPackedMsg, &prs_pdu_rel9->transmission_power, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_bandwidth, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_cyclic_prefix_type, end) && + pull8(ppReadPackedMsg, &prs_pdu_rel9->prs_muting, end)); +} + +static uint8_t unpack_dl_config_csi_rs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_csi_rs_pdu_rel10_t* csi_rs_pdu_rel10 = (nfapi_dl_config_csi_rs_pdu_rel10_t*)tlv; + + return ( pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_antenna_port_count_r10, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_resource_config_r10, end) && + pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->transmission_power, end) && + pull16(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_zero_tx_power_resource_config_bitmap_r10, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end) && + pullarray8(ppReadPackedMsg, csi_rs_pdu_rel10->csi_rs_resource_config, NFAPI_MAX_CSI_RS_RESOURCE_CONFIG, csi_rs_pdu_rel10->csi_rs_number_of_nzp_configuration, end)); +} + +static uint8_t unpack_dl_config_csi_rs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_csi_rs_pdu_rel13_t* csi_rs_pdu_rel13 = (nfapi_dl_config_csi_rs_pdu_rel13_t*)tlv; + + if (!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->csi_rs_class, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->cdm_type, end) && + pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->num_bf_vector, end))) + return 0; + + + uint16_t idx =0; + for(idx = 0; idx < csi_rs_pdu_rel13->num_bf_vector; ++idx) + { + if(!(pull8(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].csi_rs_resource_index, end))) + return 0; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : HOW TO DECODE BF VALUE \n"); + //pullarray16(ppReadPackedMsg, &csi_rs_pdu_rel13->bf_vector[idx].bf_vector, ??); + } + return 1; +} + +static uint8_t unpack_dl_config_epdcch_params_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_epdcch_parameters_rel11_t* epdcch_params_rel11 = (nfapi_dl_config_epdcch_parameters_rel11_t*)tlv; + + return (pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_resource_assignment_flag, end) && + pull16(ppReadPackedMsg, &epdcch_params_rel11->epdcch_id, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_start_symbol, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->epdcch_num_prb, end) && + pullarray8(ppReadPackedMsg, epdcch_params_rel11->epdcch_prb_index, NFAPI_MAX_EPDCCH_PRB, epdcch_params_rel11->epdcch_num_prb, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.subband_index, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel11->bf_vector.num_antennas, end) && + pullarray16(ppReadPackedMsg, epdcch_params_rel11->bf_vector.bf_value, NFAPI_MAX_NUM_ANTENNAS, epdcch_params_rel11->bf_vector.num_antennas, end)); +} + +static uint8_t unpack_dl_config_epdcch_params_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_epdcch_parameters_rel13_t* epdcch_params_rel13 = (nfapi_dl_config_epdcch_parameters_rel13_t*)tlv; + + return ( pull8(ppReadPackedMsg, &epdcch_params_rel13->dwpts_symbols, end) && + pull8(ppReadPackedMsg, &epdcch_params_rel13->initial_lbt_sf, end)); +} + +static uint8_t unpack_dl_config_mpdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_mpdcch_pdu_rel13_t* mpdcch_params_rel13 = (nfapi_dl_config_mpdcch_pdu_rel13_t*)tlv; + + + return ( pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_narrow_band, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_prb_pairs, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_assignment, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->mpdcch_tansmission_type, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->ecce_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->aggregation_level, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->rnti, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->ce_mode, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->drms_scrambling_init, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->initial_transmission_sf_io, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->transmission_power, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_format, end) && + pull16(ppReadPackedMsg, &mpdcch_params_rel13->resource_block_coding, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->mcs, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pdsch_reptition_levels, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->redundancy_version, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->new_data_indicator, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_process, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi_length, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpmi, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->pmi, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->harq_resource_offset, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->dci_subframe_repetition_number, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->tpc, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index_length, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->downlink_assignment_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->allocate_prach_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->preamble_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->prach_mask_index, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->starting_ce_level, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->srs_request, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->antenna_ports_and_scrambling_identity, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->paging_direct_indication_differentiation_flag, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->direct_indication, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &mpdcch_params_rel13->number_of_tx_antenna_ports, end) && + pullarray16(ppReadPackedMsg, mpdcch_params_rel13->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, mpdcch_params_rel13->number_of_tx_antenna_ports, end)); +} + + +static uint8_t unpack_dl_config_nbch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_nbch_pdu_rel13_t* nbch_params_rel13 = (nfapi_dl_config_nbch_pdu_rel13_t*)tlv; + + return ( pull16(ppReadPackedMsg, &nbch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&nbch_params_rel13->pdu_index, end) && + pull16(ppReadPackedMsg, &nbch_params_rel13->transmission_power, end) && + pull16(ppReadPackedMsg, &nbch_params_rel13->hyper_sfn_2_lsbs, end)); +} + +static uint8_t unpack_dl_config_npdcch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_npdcch_pdu_rel13_t* npdcch_params_rel13 = (nfapi_dl_config_npdcch_pdu_rel13_t*)tlv; + + return ( pull16(ppReadPackedMsg, &npdcch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&npdcch_params_rel13->pdu_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->ncce_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->aggregation_level, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &npdcch_params_rel13->rnti, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->scrambling_reinitialization_batch_index, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_format, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->scheduling_delay, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->resource_assignment, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->mcs, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->new_data_indicator, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->harq_ack_resource, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->npdcch_order_indication, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->starting_number_of_nprach_repetitions, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->subcarrier_indication_of_nprach, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->paging_direct_indication_differentation_flag, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->direct_indication, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->dci_subframe_repetition_number, end) && + pull8(ppReadPackedMsg, &npdcch_params_rel13->total_dci_length_including_padding, end)); +} + +static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_dl_config_ndlsch_pdu_rel13_t* ndlsch_params_rel13 = (nfapi_dl_config_ndlsch_pdu_rel13_t*)tlv; + + return ( pull16(ppReadPackedMsg, &ndlsch_params_rel13->length, end) && + pull16(ppReadPackedMsg, (uint16_t *)&ndlsch_params_rel13->pdu_index, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->start_symbol, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->rnti_type, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->rnti, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->resource_assignment, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->modulation, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->number_of_subframes_for_resource_assignment, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && + pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && + pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); +} + + +static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)msg; + + if(!(pull16(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->PDUType, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->PDUType) + { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + { + if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + { + if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + { + if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + { + if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; +} + + + + +static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_pdcch_ofdm_symbols, end) && + pull8(ppReadPackedMsg, &value->number_dci, end) && + pull16(ppReadPackedMsg, &value->number_pdu, end) && + pull8(ppReadPackedMsg, &value->number_pdsch_rnti, end) && + pull16(ppReadPackedMsg, &value->transmission_power_pcfich, end))) + return 0; + + if(value->number_pdu > NFAPI_DL_CONFIG_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_pdu, NFAPI_DL_CONFIG_MAX_PDU); + return 0; + } + + if(value->number_pdu) + { + value->dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_dl_config_request_pdu_t) * value->number_pdu, config); + if(value->dl_config_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate dl config pdu list (count:%d)\n", __FUNCTION__, value->number_pdu); + return 0; + } + } + else + { + value->dl_config_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_pdu; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_dl_config_request_pdu_t* pdu = &(value->dl_config_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + { + // pdu end of beyond buffer end + return 0; + } + + switch(pdu->pdu_type) + { + case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG, &pdu->dci_dl_pdu.dci_dl_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_BCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG, &pdu->bch_pdu.bch_pdu_rel8, &unpack_dl_config_bch_pdu_rel8_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_MCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG, &pdu->mch_pdu.mch_pdu_rel8, &unpack_dl_config_mch_pdu_rel8_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel8, &unpack_dl_config_dlsch_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel9, &unpack_dl_config_dlsch_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel10, &unpack_dl_config_dlsch_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel11, &unpack_dl_config_dlsch_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel12, &unpack_dl_config_dlsch_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG, &pdu->dlsch_pdu.dlsch_pdu_rel13, &unpack_dl_config_dlsch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_PCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG, &pdu->pch_pdu.pch_pdu_rel8, &unpack_dl_config_pch_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG, &pdu->pch_pdu.pch_pdu_rel13, &unpack_dl_config_pch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_PRS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG, &pdu->prs_pdu.prs_pdu_rel9, &unpack_dl_config_prs_pdu_rel9_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel10, &unpack_dl_config_csi_rs_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG, &pdu->csi_rs_pdu.csi_rs_pdu_rel13, &unpack_dl_config_csi_rs_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel8, &unpack_dl_config_dci_dl_pdu_rel8_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel9, &unpack_dl_config_dci_dl_pdu_rel9_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel10, &unpack_dl_config_dci_dl_pdu_rel10_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel11, &unpack_dl_config_dci_dl_pdu_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel12, &unpack_dl_config_dci_dl_pdu_rel12_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG, &pdu->epdcch_pdu.epdcch_pdu_rel13, &unpack_dl_config_dci_dl_pdu_rel13_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG, &pdu->epdcch_pdu.epdcch_params_rel11, &unpack_dl_config_epdcch_params_rel11_value}, + { NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG, &pdu->epdcch_pdu.epdcch_params_rel13, &unpack_dl_config_epdcch_params_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG, &pdu->mpdcch_pdu.mpdcch_pdu_rel13, &unpack_dl_config_mpdcch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG, &pdu->nbch_pdu.nbch_pdu_rel13, &unpack_dl_config_nbch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG, &pdu->npdcch_pdu.npdcch_pdu_rel13, &unpack_dl_config_npdcch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + + } + break; + case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG, &pdu->ndlsch_pdu.ndlsch_pdu_rel13, &unpack_dl_config_ndlsch_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + + } + break; + default: + // Need to log an error + break; + } + } + + return 1; +} + + +static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && + pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + for(int i=0;idl_tti_request_body.nGroup;i++) + { + for(int j=0;jdl_tti_request_body.nUe[i];j++) + { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) + return 0; + } + + for(int i=0;idl_tti_request_body.nPDUs;i++) + { + if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + return 0; + } + +return 1; +} + + +static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_prach_pdu_t* prach_pdu = (nfapi_nr_prach_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && + pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_pucch_pdu_t* pucch_pdu = (nfapi_nr_pucch_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && + pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && + pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && + pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && + pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && + pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && + pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && + pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_pusch_pdu_t* pusch_pdu = (nfapi_nr_pusch_pdu_t*)tlv; + + if (!( + pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && + pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && + pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && + pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && + pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && + pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && + pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && + pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && + pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && + pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && + pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map){ + case PUSCH_PDU_BITMAP_PUSCH_DATA: + { + // pack optional TLVs + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && + pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && + pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: + { + return( + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: + { + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && ++ pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && ++ pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: + { + return( + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) + ); + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + + +static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_srs_pdu_t* srs_pdu = (nfapi_nr_srs_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && + pull32(ppReadPackedMsg, &srs_pdu->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && + pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && + pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && + pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_tti_request_number_of_pdus_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t*)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) + return 0; + + + // first natch the pdu type, then call the respective function + switch(pNfapiMsg->pdu_type) + { + + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + { + if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + { + if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + { + if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + { + if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); + } + break; + + + } + + return 1; +} + + +static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_tti_request_number_of_groups_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t*)msg; + + if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) + return 0; + for (int i = 0; i < pNfapiMsg->n_ue; i++) + { + if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx ,end) ) + return 0; + } + return 1; +} + + +static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; + + if (!( + pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end) )) + return 0; + + for(int i=0; i< pNfapiMsg->n_pdus; i++) + { + if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) + return 0; + } + + for(int i=0; i< pNfapiMsg->n_group; i++) + { + if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) + return 0; + } + + return 1; +} + + + +static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->dl_config_request_body, &unpack_dl_config_request_body_value}, + }; + + return ( pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + + + + nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; + + return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel8->size, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->modulation_type, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->frequency_hopping_bits, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->new_data_indication, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->redundancy_version, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->harq_process_number, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->ul_tx_mode, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); +} + +static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &ulsch_pdu_rel10->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &ulsch_pdu_rel10->resource_block_coding, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transport_blocks, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->transmission_scheme, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->number_of_layers, end) & + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->codebook_index, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel10->disable_sequence_hopping_flag, end)); +} +static uint8_t unpack_ul_config_ulsch_pdu_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel11_t* ulsch_pdu_rel11 = (nfapi_ul_config_ulsch_pdu_rel11_t*)tlv; + + return ( pull8(ppReadPackedMsg, &ulsch_pdu_rel11->virtual_cell_id_enabled_flag, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel11->npusch_identity, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel11->dmrs_config_flag, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel11->ndmrs_csh_identity, end)); +} +static uint8_t unpack_ul_config_ulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_pdu_rel13_t* ulsch_pdu_rel13 = (nfapi_ul_config_ulsch_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &ulsch_pdu_rel13->ue_type, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->total_number_of_repetitions, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->repetition_number, end) && + pull16(ppReadPackedMsg, &ulsch_pdu_rel13->initial_transmission_sf_io, end) && + pull8(ppReadPackedMsg, &ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, end)); +} +static uint8_t unpack_ul_config_cqi_ri_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel8_t* cqi_ri_info_rel8 = (nfapi_ul_config_cqi_ri_information_rel8_t*)tlv; + + return (pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_1, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->dl_cqi_pmi_size_rank_greater_1, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->ri_size, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_cqi, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel8->delta_offset_ri, end)); +} + +static uint8_t unpack_ul_config_cqi_ri_info_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel9_t* cqi_ri_info_rel9 = (nfapi_ul_config_cqi_ri_information_rel9_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->report_type, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_cqi, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->delta_offset_ri, end))) + return 0; + + switch(cqi_ri_info_rel9->report_type) + { + case NFAPI_CSI_REPORT_TYPE_PERIODIC: + { + if(!(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size, end) && + pull8(ppReadPackedMsg, &cqi_ri_info_rel9->periodic_cqi_pmi_ri_report.control_type, end))) + return 0; + } + break; + case NFAPI_CSI_REPORT_TYPE_APERIODIC: + { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc, end) ==0) + return 0; + + uint8_t i; + for(i = 0; i < cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.number_of_cc; ++i) + { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].ri_size, end) == 0) + return 0; + + uint8_t j; + for(j = 0; j < 8; ++j) + { + if(pull8(ppReadPackedMsg, &cqi_ri_info_rel9->aperiodic_cqi_pmi_ri_report.cc[i].dl_cqi_pmi_size[j], end) == 0) + return 0; + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid report type %d \n", cqi_ri_info_rel9->report_type ); + return 0; + } + break; + }; + return 1; +} + +// NOTE : This function is a little unconventional as we uese the side to +// determine the report type +static uint8_t unpack_ul_config_cqi_ri_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_ri_information_rel13_t* cqi_ri_info_rel13 = (nfapi_ul_config_cqi_ri_information_rel13_t*)tlv; + if(cqi_ri_info_rel13->tl.length == 0) + { + cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_APERIODIC; + } + else + { + cqi_ri_info_rel13->report_type = NFAPI_CSI_REPORT_TYPE_PERIODIC; + if(pull16(ppReadPackedMsg, &cqi_ri_info_rel13->periodic_cqi_pmi_ri_report.dl_cqi_pmi_ri_size_2, end) == 0) + return 0; + } + return 1; +} +static uint8_t unpack_ul_config_cqi_init_tx_params_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_initial_transmission_parameters_rel8_t* init_tx_params_rel8 = (nfapi_ul_config_initial_transmission_parameters_rel8_t*)tlv; + + return (pull8(ppReadPackedMsg, &init_tx_params_rel8->n_srs_initial, end) && + pull8(ppReadPackedMsg, &init_tx_params_rel8->initial_number_of_resource_blocks, end)); +} +static uint8_t unpack_ul_config_ulsch_harq_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_harq_information_rel10_t* harq_info_rel10 = (nfapi_ul_config_ulsch_harq_information_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &harq_info_rel10->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_rel10->delta_offset_harq, end) && + pull8(ppReadPackedMsg, &harq_info_rel10->ack_nack_mode, end)); +} + +static uint8_t unpack_ul_config_ulsch_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ulsch_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_ulsch_harq_information_rel13_t*)tlv; + + return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->delta_offset_harq_2, end)); +} + +static uint8_t unpack_ul_config_ue_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel8_t* ue_info_rel8 = (nfapi_ul_config_ue_information_rel8_t*)tlv; + + return (pull32(ppReadPackedMsg, &ue_info_rel8->handle, end) && + pull16(ppReadPackedMsg, (uint16_t *)&ue_info_rel8->rnti, end)); +} +static uint8_t unpack_ul_config_ue_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel11_t* ue_info_rel11 = (nfapi_ul_config_ue_information_rel11_t*)tlv; + + return (pull8(ppReadPackedMsg, &ue_info_rel11->virtual_cell_id_enabled_flag, end) && + pull16(ppReadPackedMsg, &ue_info_rel11->npusch_identity, end)); +} +static uint8_t unpack_ul_config_ue_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_ue_information_rel13_t* ue_info_rel13 = (nfapi_ul_config_ue_information_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &ue_info_rel13->ue_type, end) && + pull8(ppReadPackedMsg, &ue_info_rel13->empty_symbols, end) && + pull16(ppReadPackedMsg, &ue_info_rel13->total_number_of_repetitions, end) && + pull16(ppReadPackedMsg, &ue_info_rel13->repetition_number, end)); +} + +static uint8_t unpack_ul_config_cqi_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel8_t* cqi_info_rel8 = (nfapi_ul_config_cqi_information_rel8_t*)tlv; + + return ( pull16(ppReadPackedMsg, &cqi_info_rel8->pucch_index, end) && + pull8(ppReadPackedMsg, &cqi_info_rel8->dl_cqi_pmi_size, end)); +} +static uint8_t unpack_ul_config_cqi_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel10_t* cqi_info_rel10 = (nfapi_ul_config_cqi_information_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &cqi_info_rel10->number_of_pucch_resource, end) && + pull16(ppReadPackedMsg, &cqi_info_rel10->pucch_index_p1, end)); +} +static uint8_t unpack_ul_config_cqi_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_cqi_information_rel13_t* cqi_info_rel13 = (nfapi_ul_config_cqi_information_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &cqi_info_rel13->csi_mode, end) && + pull16(ppReadPackedMsg, &cqi_info_rel13->dl_cqi_pmi_size_2, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->starting_prb, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->n_prb, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->cdm_index, end) && + pull8(ppReadPackedMsg, &cqi_info_rel13->n_srs, end)); +} + +static uint8_t unpack_ul_config_sr_info_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_sr_information_rel8_t* sr_info_rel8 = (nfapi_ul_config_sr_information_rel8_t*)tlv; + + return ( pull16(ppReadPackedMsg, &sr_info_rel8->pucch_index, end)); +} + +static uint8_t unpack_ul_config_sr_info_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_sr_information_rel10_t* sr_info_rel10 = (nfapi_ul_config_sr_information_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &sr_info_rel10->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &sr_info_rel10->pucch_index_p1, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel10_tdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel10_tdd_t* harq_info_tdd_rel10 = (nfapi_ul_config_harq_information_rel10_tdd_t*)tlv; + + return (pull8(ppReadPackedMsg, &harq_info_tdd_rel10->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_tdd_rel10->ack_nack_mode, end) && + pull8(ppReadPackedMsg, &harq_info_tdd_rel10->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_0, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_1, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_2, end) && + pull16(ppReadPackedMsg, &harq_info_tdd_rel10->n_pucch_1_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel8_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel8_fdd_t* harq_info_fdd_rel8 = (nfapi_ul_config_harq_information_rel8_fdd_t*)tlv; + + return (pull16(ppReadPackedMsg, &harq_info_fdd_rel8->n_pucch_1_0, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel8->harq_size, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel9_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel9_fdd_t* harq_info_fdd_rel9 = (nfapi_ul_config_harq_information_rel9_fdd_t*)tlv; + + return (pull8(ppReadPackedMsg, &harq_info_fdd_rel9->harq_size, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel9->ack_nack_mode, end) && + pull8(ppReadPackedMsg, &harq_info_fdd_rel9->number_of_pucch_resources, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_0, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_1, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_2, end) && + pull16(ppReadPackedMsg, &harq_info_fdd_rel9->n_pucch_1_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel11_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel11_t* harq_info_rel11 = (nfapi_ul_config_harq_information_rel11_t*)tlv; + + return (pull8(ppReadPackedMsg, &harq_info_rel11->num_ant_ports, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_0, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_1, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_2, end) && + pull16(ppReadPackedMsg, &harq_info_rel11->n_pucch_2_3, end)); +} + +static uint8_t unpack_ul_config_harq_info_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_harq_information_rel13_t* harq_info_rel13 = (nfapi_ul_config_harq_information_rel13_t*)tlv; + + return (pull16(ppReadPackedMsg, &harq_info_rel13->harq_size_2, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->starting_prb, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->n_prb, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->cdm_index, end) && + pull8(ppReadPackedMsg, &harq_info_rel13->n_srs, end)); +} + + +static uint8_t unpack_ul_config_srs_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel8_t* srs_pdu_rel8 = (nfapi_ul_config_srs_pdu_rel8_t*)tlv; + + return (pull32(ppReadPackedMsg, &srs_pdu_rel8->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->size, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_bandwidth, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->frequency_domain_position, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->srs_hopping_bandwidth, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->transmission_comb, end) && + pull16(ppReadPackedMsg, &srs_pdu_rel8->i_srs, end) && + pull8(ppReadPackedMsg, &srs_pdu_rel8->sounding_reference_cyclic_shift, end)); +} + +static uint8_t unpack_ul_config_srs_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel10_t* srs_pdu_rel10 = (nfapi_ul_config_srs_pdu_rel10_t*)tlv; + return pull8(ppReadPackedMsg, &srs_pdu_rel10->antenna_port, end); +} + +static uint8_t unpack_ul_config_srs_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_srs_pdu_rel13_t* srs_pdu_rel13 = (nfapi_ul_config_srs_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &srs_pdu_rel13->number_of_combs, end)); +} + +static uint8_t unpack_ul_nb_harq_info_rel13_fdd_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_nb_harq_information_rel13_fdd_t* nb_harq_info_fdd_rel13 = (nfapi_ul_config_nb_harq_information_rel13_fdd_t*)tlv; + + return (pull8(ppReadPackedMsg, &nb_harq_info_fdd_rel13->harq_ack_resource, end)); +} + +static uint8_t unpack_ul_config_nulsch_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_nulsch_pdu_rel13_t* nulsch_pdu_rel13 = (nfapi_ul_config_nulsch_pdu_rel13_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &nulsch_pdu_rel13->nulsch_format, end) && + pull32(ppReadPackedMsg, &nulsch_pdu_rel13->handle, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->size, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->rnti, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->subcarrier_indication, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->resource_assignment, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->mcs, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->redudancy_version, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->repetition_number, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->new_data_indication, end) && + pull8(ppReadPackedMsg, &nulsch_pdu_rel13->n_srs, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->scrambling_sequence_initialization_cinit, end) && + pull16(ppReadPackedMsg, &nulsch_pdu_rel13->sf_idx, end))) + return 0; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &nulsch_pdu_rel13->ue_information.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, + { NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG, &nulsch_pdu_rel13->nb_harq_information.nb_harq_information_rel13_fdd, &unpack_ul_nb_harq_info_rel13_fdd_value}, + }; + + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, 0, 0); +} + +static uint8_t unpack_ul_config_nrach_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_config_nrach_pdu_rel13_t* nrach_pdu_rel13 = (nfapi_ul_config_nrach_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_0, end) && + pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_1, end) && + pull8(ppReadPackedMsg, &nrach_pdu_rel13->nprach_config_2, end)); +} + + +static uint8_t unpack_ul_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + #define UL_CONFIG_ULSCH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &_pdu.ulsch_pdu_rel8, &unpack_ul_config_ulsch_pdu_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG, &_pdu.ulsch_pdu_rel10, &unpack_ul_config_ulsch_pdu_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG, &_pdu.ulsch_pdu_rel11, &unpack_ul_config_ulsch_pdu_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG, &_pdu.ulsch_pdu_rel13, &unpack_ul_config_ulsch_pdu_rel13_value}, + + #define UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG, &_pdu.cqi_ri_information_rel8, &unpack_ul_config_cqi_ri_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG, &_pdu.cqi_ri_information_rel9, &unpack_ul_config_cqi_ri_info_rel9_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG, &_pdu.cqi_ri_information_rel13, &unpack_ul_config_cqi_ri_info_rel13_value}, + + #define UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG, &_pdu.harq_information_rel10, &unpack_ul_config_ulsch_harq_info_rel10_value},\ + { NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_ulsch_harq_info_rel13_value}, + + #define UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG, &_pdu.initial_transmission_parameters_rel8, &unpack_ul_config_cqi_init_tx_params_rel8_value}, + + #define UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG, &_pdu.ue_information_rel8, &unpack_ul_config_ue_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG, &_pdu.ue_information_rel11, &unpack_ul_config_ue_info_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG, &_pdu.ue_information_rel13, &unpack_ul_config_ue_info_rel13_value}, + + #define UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG, &_pdu.cqi_information_rel8, &unpack_ul_config_cqi_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG, &_pdu.cqi_information_rel10, &unpack_ul_config_cqi_info_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG, &_pdu.cqi_information_rel13, &unpack_ul_config_cqi_info_rel13_value}, + + #define UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG, &_pdu.sr_information_rel8, &unpack_ul_config_sr_info_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG, &_pdu.sr_information_rel10, &unpack_ul_config_sr_info_rel10_value}, + + #define UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG, &_pdu.harq_information_rel10_tdd, &unpack_ul_config_harq_info_rel10_tdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG, &_pdu.harq_information_rel8_fdd, &unpack_ul_config_harq_info_rel8_fdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG, &_pdu.harq_information_rel9_fdd, &unpack_ul_config_harq_info_rel9_fdd_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG, &_pdu.harq_information_rel11, &unpack_ul_config_harq_info_rel11_value}, \ + { NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG, &_pdu.harq_information_rel13, &unpack_ul_config_harq_info_rel13_value}, + + #define UL_CONFIG_SRS_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG, &_pdu.srs_pdu_rel8, &unpack_ul_config_srs_pdu_rel8_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG, &_pdu.srs_pdu_rel10, &unpack_ul_config_srs_pdu_rel10_value}, \ + { NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG, &_pdu.srs_pdu_rel13, &unpack_ul_config_srs_pdu_rel13_value}, + + #define UL_CONFIG_NULSCH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG, &_pdu.nulsch_pdu_rel13, &unpack_ul_config_nulsch_pdu_rel13_value}, + + #define UL_CONFIG_NRACH_PDU_UNPACK_FNS(_pdu) \ + { NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG, &_pdu.nrach_pdu_rel13, &unpack_ul_config_nrach_pdu_rel13_value}, + + + nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->number_of_pdus, end) && + pull8(ppReadPackedMsg, &value->rach_prach_frequency_resources, end) && + pull8(ppReadPackedMsg, &value->srs_present, end))) + return 0; + + if(value->number_of_pdus > NFAPI_UL_CONFIG_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of ul config pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_UL_CONFIG_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) + { + value->ul_config_pdu_list = (nfapi_ul_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_ul_config_request_pdu_t) * value->number_of_pdus, config); + + if(value->ul_config_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate ul config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } + else + { + value->ul_config_pdu_list = 0; + } + + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_ul_config_request_pdu_t* pdu = &(value->ul_config_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + { + // pdu end is past buffer end + return 0; + } + + switch(pdu->pdu_type) + { + case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_pdu) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + + case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.ulsch_pdu) + UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.cqi_ri_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_ri_pdu.initial_transmission_parameters) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_harq_pdu.ulsch_pdu) + UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_harq_pdu.harq_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_harq_pdu.initial_transmission_parameters) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu) + UL_CONFIG_CQI_RI_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.cqi_ri_information) + UL_CONFIG_ULSCH_HARQ_INFO_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.harq_information) + UL_CONFIG_INIT_TX_PARAMS_UNPACK_FNS(pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_pdu.cqi_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_pdu.ue_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_pdu.sr_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_harq_pdu.ue_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.ue_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.sr_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_sr_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.cqi_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.cqi_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_pdu.sr_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.ue_information) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.cqi_information) + UL_CONFIG_UCI_SR_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.sr_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->uci_cqi_sr_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_SRS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_SRS_PDU_UNPACK_FNS(pdu->srs_pdu) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_UCI_UE_INFO_UNPACK_FNS(pdu->harq_buffer_pdu.ue_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.ulsch_pdu) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_uci_csi_pdu.csi_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.ulsch_pdu) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_uci_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_ULSCH_PDU_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu) + UL_CONFIG_UCI_CQI_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.csi_information) + UL_CONFIG_UCI_HARQ_INFO_UNPACK_FNS(pdu->ulsch_csi_uci_harq_pdu.harq_information) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_NULSCH_PDU_UNPACK_FNS(pdu->nulsch_pdu) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + UL_CONFIG_NRACH_PDU_UNPACK_FNS(pdu->nrach_pdu) + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + } + } + return 1; +} + + +static uint8_t unpack_ul_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_UL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->ul_config_request_body, &unpack_ul_config_request_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_hi_dci0_hi_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_hi_pdu_rel8_t* hi_pdu_rel8 = (nfapi_hi_dci0_hi_pdu_rel8_t*)tlv; + + return( pull8(ppReadPackedMsg, &hi_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->hi_value, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel8->i_phich, end) && + pull16(ppReadPackedMsg, &hi_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_hi_dci0_hi_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_hi_pdu_rel10_t* hi_pdu_rel10 = (nfapi_hi_dci0_hi_pdu_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &hi_pdu_rel10->flag_tb2, end) && + pull8(ppReadPackedMsg, &hi_pdu_rel10->hi_value_2, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel8_t* dci_pdu_rel8 = (nfapi_hi_dci0_dci_pdu_rel8_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_pdu_rel8->dci_format, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cce_index, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->aggregation_level, end) && + pull16(ppReadPackedMsg, &dci_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->resource_block_start, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->number_of_resource_block, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->mcs_1, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cyclic_shift_2_for_drms, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_enabled_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->frequency_hopping_bits, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->new_data_indication_1, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->ue_tx_antenna_seleciton, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->tpc, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->cqi_csi_request, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->ul_index, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel8->dl_assignment_index, end) && + pull32(ppReadPackedMsg, &dci_pdu_rel8->tpc_bitmap, end) && + pull16(ppReadPackedMsg, &dci_pdu_rel8->transmission_power, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel10_t* dci_pdu_rel10 = (nfapi_hi_dci0_dci_pdu_rel10_t*)tlv; + + return (pull8(ppReadPackedMsg, &dci_pdu_rel10->cross_carrier_scheduling_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->carrier_indicator, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->size_of_cqi_csi_feild, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->srs_request, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_flag, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->resource_allocation_type, end) && + pull32(ppReadPackedMsg, &dci_pdu_rel10->resource_block_coding, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->mcs_2, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->new_data_indication_2, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->number_of_antenna_ports, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->tpmi, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->total_dci_length_including_padding, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel10->n_ul_rb, end)); +} + +static uint8_t unpack_hi_dci0_dci_pdu_rel12_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_dci_pdu_rel12_t* dci_pdu_rel12 = (nfapi_hi_dci0_dci_pdu_rel12_t*)tlv; + + return ( pull8(ppReadPackedMsg, &dci_pdu_rel12->pscch_resource, end) && + pull8(ppReadPackedMsg, &dci_pdu_rel12->time_resource_pattern, end)); +} + +static uint8_t unpack_hi_dci0_mpdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->mpdcch_narrowband, end) && + pull8(ppReadPackedMsg, &value->number_of_prb_pairs, end) && + pull8(ppReadPackedMsg, &value->resource_block_assignment, end) && + pull8(ppReadPackedMsg, &value->mpdcch_transmission_type, end) && + pull8(ppReadPackedMsg, &value->start_symbol, end) && + pull8(ppReadPackedMsg, &value->ecce_index, end) && + pull8(ppReadPackedMsg, &value->aggreagation_level, end) && + pull8(ppReadPackedMsg, &value->rnti_type, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->ce_mode, end) && + pull16(ppReadPackedMsg, &value->drms_scrambling_init, end) && + pull16(ppReadPackedMsg, &value->initial_transmission_sf_io, end) && + pull16(ppReadPackedMsg, &value->transmission_power, end) && + pull8(ppReadPackedMsg, &value->dci_format, end) && + pull8(ppReadPackedMsg, &value->resource_block_start, end) && + pull8(ppReadPackedMsg, &value->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &value->mcs, end) && + pull8(ppReadPackedMsg, &value->pusch_repetition_levels, end) && + pull8(ppReadPackedMsg, &value->frequency_hopping_flag, end) && + pull8(ppReadPackedMsg, &value->new_data_indication, end) && + pull8(ppReadPackedMsg, &value->harq_process, end) && + pull8(ppReadPackedMsg, &value->redudency_version, end) && + pull8(ppReadPackedMsg, &value->tpc, end) && + pull8(ppReadPackedMsg, &value->csi_request, end) && + pull8(ppReadPackedMsg, &value->ul_inex, end) && + pull8(ppReadPackedMsg, &value->dai_presence_flag, end) && + pull8(ppReadPackedMsg, &value->dl_assignment_index, end) && + pull8(ppReadPackedMsg, &value->srs_request, end) && + pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end) && + pull32(ppReadPackedMsg, &value->tcp_bitmap, end) && + pull8(ppReadPackedMsg, &value->total_dci_length_include_padding, end) && + pull8(ppReadPackedMsg, &value->number_of_tx_antenna_ports, end) && + pullarray16(ppReadPackedMsg, value->precoding_value, NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS, value->number_of_tx_antenna_ports, end)); +} + +static uint8_t unpack_hi_dci0_npdcch_dci_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_hi_dci0_npdcch_dci_pdu_rel13_t* value = (nfapi_hi_dci0_npdcch_dci_pdu_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->ncce_index, end) && + pull8(ppReadPackedMsg, &value->aggregation_level, end) && + pull8(ppReadPackedMsg, &value->start_symbol, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->scrambling_reinitialization_batch_index, end) && + pull8(ppReadPackedMsg, &value->nrs_antenna_ports_assumed_by_the_ue, end) && + pull8(ppReadPackedMsg, &value->subcarrier_indication, end) && + pull8(ppReadPackedMsg, &value->resource_assignment, end) && + pull8(ppReadPackedMsg, &value->scheduling_delay, end) && + pull8(ppReadPackedMsg, &value->mcs, end) && + pull8(ppReadPackedMsg, &value->redudancy_version, end) && + pull8(ppReadPackedMsg, &value->repetition_number, end) && + pull8(ppReadPackedMsg, &value->new_data_indicator, end) && + pull8(ppReadPackedMsg, &value->dci_subframe_repetition_number, end)); +} + +static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_hi_dci0_request_body_t* value = (nfapi_hi_dci0_request_body_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->sfnsf, end) && + pull8(ppReadPackedMsg, &value->number_of_dci, end) && + pull8(ppReadPackedMsg, &value->number_of_hi, end))) + return 0; + + uint8_t totalNumPdus = value->number_of_hi + value->number_of_dci; + + if(totalNumPdus > NFAPI_HI_DCI0_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of dci0 pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, totalNumPdus, NFAPI_HI_DCI0_MAX_PDU); + return 0; + } + + if(totalNumPdus > 0) + { + value->hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_hi_dci0_request_pdu_t) * totalNumPdus, config); + if(value->hi_dci0_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate hi dci0 pdu list (count:%d)\n", __FUNCTION__, totalNumPdus); + return 0; + } + } + else + { + value->hi_dci0_pdu_list = 0; + } + + uint8_t i; + for(i = 0; i < totalNumPdus; ++i) + { + nfapi_hi_dci0_request_pdu_t* pdu = &(value->hi_dci0_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + { + // pdu end if past buffer end + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s pdu size to big %d %d\n", __FUNCTION__, packedPduEnd, end); + return 0; + } + + switch(pdu->pdu_type) + { + case NFAPI_HI_DCI0_HI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG, &pdu->hi_pdu.hi_pdu_rel8, &unpack_hi_dci0_hi_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG, &pdu->hi_pdu.hi_pdu_rel10, &unpack_hi_dci0_hi_pdu_rel10_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_HI_DCI0_DCI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG, &pdu->dci_pdu.dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG, &pdu->dci_pdu.dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, + { NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG, &pdu->dci_pdu.dci_pdu_rel12, &unpack_hi_dci0_dci_pdu_rel12_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel8, &unpack_hi_dci0_dci_pdu_rel8_value}, + { NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG, &pdu->epdcch_dci_pdu.epdcch_dci_pdu_rel10, &unpack_hi_dci0_dci_pdu_rel10_value}, + { NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG, &pdu->epdcch_dci_pdu.epdcch_parameters_rel11, &unpack_dl_config_epdcch_params_rel11_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG, &pdu->mpdcch_dci_pdu.mpdcch_dci_pdu_rel13, &unpack_hi_dci0_mpdcch_dci_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG, &pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13, &unpack_hi_dci0_npdcch_dci_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid pdu type %d \n", pdu->pdu_type ); + } + break; + }; + } + + return 1; +} +//unpack_ul_dci_pdu_list_value + +static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!(pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && + + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && + + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end))) + + return 0; + } + + return (pull16(ppReadPackedMsg, &value->PDUType, end) && + pull16(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); + +} + +static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ +nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) + )) + return 0; + for(int i=0; i< pNfapiMsg->numPdus; i++) + { + if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) + return 0; + } + + return 1; + +} + +static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_HI_DCI0_REQUEST_BODY_TAG, &pNfapiMsg->hi_dci0_request_body, &unpack_hi_dci0_request_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + +} +static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_pdu_t* pNfapiMsg = (nfapi_nr_pdu_t*)msg; + + if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) + )) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; + for(; i < total_number_of_tlvs; ++i) + { + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) + return 0; + + switch(pNfapiMsg->TLVs[i].tag){ + case 0: + { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, 16384, pNfapiMsg->TLVs[i].length, end)) + return 0; + break; + + } + + case 1: + { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, pNfapiMsg->TLVs[i].length , pNfapiMsg->TLVs[i].length, end)) + return 0; + break; + + } + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); + break; + } + + } + } + + + return 1; +} + +static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) + return 0; + + for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) + { + if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) + return 0; + } + + return 1; +} + +static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t proceed = 1; + nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; + + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; + + while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) + { + nfapi_tl_t generic_tl; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_TX_REQUEST_BODY_TAG: + { + pNfapiMsg->tx_request_body.tl = generic_tl; + + if( pull16(ppReadPackedMsg, &pNfapiMsg->tx_request_body.number_of_pdus, end) == 0) + return 0; + + if(pNfapiMsg->tx_request_body.number_of_pdus > NFAPI_TX_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of tx pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus, NFAPI_TX_MAX_PDU); + return 0; + } + + if(pNfapiMsg->tx_request_body.number_of_pdus > 0) + { + pNfapiMsg->tx_request_body.tx_pdu_list = (nfapi_tx_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_tx_request_pdu_t) * pNfapiMsg->tx_request_body.number_of_pdus, config); + if(pNfapiMsg->tx_request_body.tx_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate tx pdu list (count:%d)\n", __FUNCTION__, pNfapiMsg->tx_request_body.number_of_pdus); + return 0; + } + } + else + { + pNfapiMsg->tx_request_body.tx_pdu_list = 0; + } + + + uint16_t i; + uint16_t totalNumPdus = pNfapiMsg->tx_request_body.number_of_pdus; + for(i = 0; i < totalNumPdus; ++i) + { + nfapi_tx_request_pdu_t* pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); + if (pdu) { + uint16_t length = 0; + uint16_t index = 0; + + if(!(pull16(ppReadPackedMsg, &length, end) && + pull16(ppReadPackedMsg, &index, end))) + return 0; + + pdu->pdu_length = length; + pdu->pdu_index = index; + + + // TODO : May need to rethink this bit + pdu->num_segments = 1; + pdu->segments[0].segment_length = pdu->pdu_length; + pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); + + if(pdu->segments[0].segment_data) + { + if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) + return 0; + if (pdu->segments[0].segment_length == 3) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, + pdu->segments[0].segment_data[0], + pdu->segments[0].segment_data[1], + pdu->segments[0].segment_data[2] + ); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request FIXME : Invalid pdu type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + + +//UNPACK NR UPLINK INDICATION FUNCTIONS + +//RX DATA INDICATION + +static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_rx_data_pdu_t* value = (nfapi_nr_rx_data_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull16(ppReadPackedMsg, &value->pdu_length, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + return 1; +} + + +static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + // uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message rx data indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; + + printf("\n"); + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end)) + return 0; + } + +return 1; +} + +//NR CRC INDICATION + +static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->harq_id, end) && + pull8(ppReadPackedMsg, &value->tb_crc_status, end) && + pull16(ppReadPackedMsg, &value->num_cb, end) && + //pullarray8(ppReadPackedMsg, value->cb_crc_status, (int)(value->num_cb / 8) + 1, (int)(value->num_cb / 8) + 1, end) && //length is ceil(NumCb/8) + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + + return 1; +} + +static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t *ptr = *ppReadPackedMsg; + // printf("\n Read P7 message indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) + )) + return 0; + + for(int i=0; inumber_crcs;i++) + { + if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//SRS INDICATION + +static uint8_t unpack_nr_srs_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_srs_indication_pdu_t* value = (nfapi_nr_srs_indication_pdu_t*)tlv; + + if(!(pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->num_symbols, end) && + pull8(ppReadPackedMsg, &value->wide_band_snr, end) && + pull8(ppReadPackedMsg, &value->num_reported_symbols, end) && + pull16(ppReadPackedMsg, &value->reported_symbol_list->num_rbs, end) + )) + return 0; + for(int i = 0; i < value->reported_symbol_list->num_rbs; i++) + { + if(!(pull8(ppReadPackedMsg, &value->reported_symbol_list->rb_list->rb_snr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_srs_indication_t *pNfapiMsg = (nfapi_nr_srs_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg,&pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg,&pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; inumber_of_pdus;i++) + { + if(!unpack_nr_srs_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR RACH + +static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->phy_cell_id, end) && + pull8(ppReadPackedMsg, &value->symbol_index, end) && + pull8(ppReadPackedMsg, &value->slot_index, end) && + pull8(ppReadPackedMsg, &value->freq_index, end) && + pull8(ppReadPackedMsg, &value->avg_rssi, end) && + pull8(ppReadPackedMsg, &value->avg_snr, end) && + pull8(ppReadPackedMsg, &value->num_preamble, end) + )) + return 0; + for(int i = 0; i < value->num_preamble; i++) + { + if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && + pull16(ppReadPackedMsg, &value->preamble_list->timing_advance, end) && + pull32(ppReadPackedMsg, &value->preamble_list->preamble_pwr, end) + )) + return 0; + } + return 1; +} + +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { + + nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) + )) + return 0; + + for(int i=0; i< pNfapiMsg->number_of_pdus;i++) + { + if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + +//NR UCI + +static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; + + uint8_t *ptr = *ppReadPackedMsg; + printf("\n Read P7 message uci_0_1 indication unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && + pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) + )) + return 0; + } + + // if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + // uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value + // temp = (uint8_t*) malloc(sizeof(uint8_t)); + // //printf("value->harq->num_harq = %d \n", value->harq->num_harq); + // // if(!(pull8(ppReadPackedMsg, temp, end) && + // // pull8(ppReadPackedMsg, temp, end) + // // )) + // // return 0; + + // // for(int i=0; i<1;i++) + // // { + // // if(!(pull8(ppReadPackedMsg, temp, end) + // // )) + // // return 0; + // // } + // } + + return 1; +} + + +static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; + + if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && + pull32(ppReadPackedMsg, &value->handle, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->pucch_format, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull16(ppReadPackedMsg, &value->rssi, end) + )) + return 0; + if (value->pduBitmap & 0x01) { //SR + if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) && + pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) && + pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) && + pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 + if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) && + pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) && + pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) + )) + return 0; + } + + if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 + if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) && + pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) && + pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) + )) + return 0; + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && + pull16(ppReadPackedMsg, &value->pdu_size, end) + )) + return 0; + + switch (value->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); + break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; + unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end); + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; + unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end); + break; + } + } + + return 1; +} + +static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_uci_indication_t *pNfapiMsg = (nfapi_nr_uci_indication_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->num_ucis, end) + )) + return 0; + + for(int i=0; inum_ucis;i++) + { + if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end)) + return 0; + } + +return 1; +} + + +static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t proceed = 1; + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; + + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; + + while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) + { + nfapi_tl_t generic_tl; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_UE_RELEASE_BODY_TAG: + { + pNfapiMsg->ue_release_request_body.tl = generic_tl; + if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) + return 0; + + if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); + return 0; + } else { + uint8_t j; + uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; + for(j = 0; j < num; ++j){ + if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){ + return 0; + } + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + +static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->value_0, end) && + pull8(ppReadPackedMsg, &value->value_1, end)); +} + +static uint8_t unpack_harq_indication_tdd_harq_data_multiplexing(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_harq_data_multiplexing_t* value = (nfapi_harq_indication_tdd_harq_data_multiplexing_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->value_0, end) && + pull8(ppReadPackedMsg, &value->value_1, end) && + pull8(ppReadPackedMsg, &value->value_2, end) && + pull8(ppReadPackedMsg, &value->value_3, end)); +} +static uint8_t unpack_harq_indication_tdd_harq_data_special_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_harq_data_special_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_special_bundling_t*)tlv; + return ( pull8(ppReadPackedMsg, &value->value_0, end)); +} +static uint8_t unpack_harq_indication_tdd_harq_data(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_harq_data_t* value = (nfapi_harq_indication_tdd_harq_data_t*)tlv; + return (pull8(ppReadPackedMsg, &value->value_0, end)); +} + +static uint8_t unpack_harq_indication_tdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel8_t* value = (nfapi_harq_indication_tdd_rel8_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + uint8_t result = 0; + switch(value->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_bundling(&value->harq_data.bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data_multiplexing(&value->harq_data.multiplex, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data.special_bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = 1; + break; + default: + // TODO add error message + return 0; + break; + } + return result; +} + +static uint8_t unpack_harq_indication_tdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel9_t* value = (nfapi_harq_indication_tdd_rel9_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) + { + // TODO : add error message + return 0; + } + + uint16_t idx = 0; + for(idx = 0; idx < value->number_of_ack_nack; ++idx) + { + uint8_t result = 0; + switch(value->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); + break; + default: + // TODO add error message + return 0; + break; + } + + if(result == 0) + return 0; + } + return 1; +} + +static uint8_t unpack_harq_indication_tdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_tdd_rel13_t* value = (nfapi_harq_indication_tdd_rel13_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->mode, end) && + pull16(ppReadPackedMsg, &value->number_of_ack_nack, end))) + return 0; + + if(value->number_of_ack_nack > NFAPI_MAX_NUMBER_ACK_NACK_TDD) + { + // TODO : add error message + return 0; + } + + uint16_t idx = 0; + for(idx = 0; idx < value->number_of_ack_nack; ++idx) + { + uint8_t result = 0; + switch(value->mode) + { + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].multiplex, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING: + result = unpack_harq_indication_tdd_harq_data_special_bundling(&value->harq_data[idx].special_bundling, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].channel_selection, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_3, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_4, ppReadPackedMsg, end); + break; + case NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5: + result = unpack_harq_indication_tdd_harq_data(&value->harq_data[idx].format_5, ppReadPackedMsg, end); + break; + default: + // TODO add error message + return 0; + break; + } + + if(result == 0) + return 0; + } + return 1; +} + +static uint8_t unpack_harq_indication_fdd_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel8_t* value = (nfapi_harq_indication_fdd_rel8_t*)tlv; + return (pull8(ppReadPackedMsg, &value->harq_tb1, end) && + pull8(ppReadPackedMsg, &value->harq_tb2, end)); +} + +static uint8_t unpack_harq_indication_fdd_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel9_t* value = (nfapi_harq_indication_fdd_rel9_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->mode, end) && + pull8(ppReadPackedMsg, &value->number_of_ack_nack, end) && + pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL9_MAX, value->number_of_ack_nack, end)); +} + +static uint8_t unpack_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_harq_indication_fdd_rel13_t* value = (nfapi_harq_indication_fdd_rel13_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->mode, end) && + pull16(ppReadPackedMsg, &value->number_of_ack_nack, end) && + pullarray8(ppReadPackedMsg, value->harq_tb_n, NFAPI_HARQ_ACK_NACK_REL13_MAX, value->number_of_ack_nack, end)); +} + +static uint8_t unpack_ul_cqi_information_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_ul_cqi_information_t* value = (nfapi_ul_cqi_information_t*)tlv; + + return (pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull8(ppReadPackedMsg, &value->channel, end)); +} + + + +static uint8_t unpack_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_harq_indication_body_t* value = (nfapi_harq_indication_body_t*)tlv; + uint8_t* harqBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(harqBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) + return 0; + + if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); + return 0; + } + + value->harq_pdu_list = (nfapi_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_harq_indication_pdu_t) * value->number_of_harqs, config); + if(value->harq_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); + return 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_harqs; ++i) + { + nfapi_harq_indication_pdu_t* pdu = &(value->harq_pdu_list[i]); + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_HARQ_INDICATION_TDD_REL8_TAG, &pdu->harq_indication_tdd_rel8, &unpack_harq_indication_tdd_rel8_value}, + { NFAPI_HARQ_INDICATION_TDD_REL9_TAG, &pdu->harq_indication_tdd_rel9, &unpack_harq_indication_tdd_rel9_value}, + { NFAPI_HARQ_INDICATION_TDD_REL13_TAG, &pdu->harq_indication_tdd_rel13, &unpack_harq_indication_tdd_rel13_value}, + { NFAPI_HARQ_INDICATION_FDD_REL8_TAG, &pdu->harq_indication_fdd_rel8, &unpack_harq_indication_fdd_rel8_value}, + { NFAPI_HARQ_INDICATION_FDD_REL9_TAG, &pdu->harq_indication_fdd_rel9, &unpack_harq_indication_fdd_rel9_value}, + { NFAPI_HARQ_INDICATION_FDD_REL13_TAG, &pdu->harq_indication_fdd_rel13, &unpack_harq_indication_fdd_rel13_value}, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) + return 0; + + } + + return 1; +} + +static uint8_t unpack_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_harq_indication_t *pNfapiMsg = (nfapi_harq_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->harq_indication_body, &unpack_harq_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_crc_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_crc_indication_rel8_t* crc_pdu_rel8 = (nfapi_crc_indication_rel8_t*)tlv; + return ( pull8(ppReadPackedMsg, &crc_pdu_rel8->crc_flag, end) ); +} + +static uint8_t unpack_crc_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_crc_indication_body_t* value = (nfapi_crc_indication_body_t*)tlv; + uint8_t* crcBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(crcBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_crcs, end) == 0) + return 0; + + if(value->number_of_crcs > NFAPI_CRC_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of crc ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_crcs, NFAPI_CRC_IND_MAX_PDU); + return 0; + } + + if(value->number_of_crcs > 0) + { + value->crc_pdu_list = (nfapi_crc_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_crc_indication_pdu_t) * value->number_of_crcs, config); + if(value->crc_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate crc ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_crcs); + return 0; + } + } + else + { + value->crc_pdu_list = 0; + } + + + uint8_t i = 0; + for(i = 0; i < value->number_of_crcs; ++i) + { + nfapi_crc_indication_pdu_t* pdu = &(value->crc_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* crcPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_CRC_INDICATION_REL8_TAG, &pdu->crc_indication_rel8, unpack_crc_indication_rel8_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, crcPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; +} + +static uint8_t unpack_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_crc_indication_t *pNfapiMsg = (nfapi_crc_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_CRC_INDICATION_BODY_TAG, &pNfapiMsg->crc_indication_body, &unpack_crc_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_rx_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_rx_indication_rel8_t* value = (nfapi_rx_indication_rel8_t*)tlv; + + return (pull16(ppReadPackedMsg, &value->length, end) && + pull16(ppReadPackedMsg, &value->offset, end) && + pull8(ppReadPackedMsg, &value->ul_cqi, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end)); +} +static uint8_t unpack_rx_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_rx_indication_rel9_t* value = (nfapi_rx_indication_rel9_t*)tlv; + return (pull16(ppReadPackedMsg, &value->timing_advance_r9, end)); +} + +static uint8_t unpack_rx_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_rx_indication_body_t* value = (nfapi_rx_indication_body_t*)tlv; + + // the rxBodyEnd points to the end of the cqi PDU's + uint8_t* rxBodyEnd = *ppReadPackedMsg + value->tl.length; + uint8_t* rxPduEnd = rxBodyEnd; + + uint8_t* numberOfPdusAddress = *ppReadPackedMsg; + + if(rxBodyEnd > end) + { + // pdu end is past buffer end + return 0; + } + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_RX_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of rx ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_RX_IND_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) + { + value->rx_pdu_list = (nfapi_rx_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_rx_indication_pdu_t) * value->number_of_pdus, config); + if(value->rx_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate rx ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } + else + { + value->rx_pdu_list = 0; + } + + uint8_t i = 0; + nfapi_rx_indication_pdu_t* pdu = 0; + while((uint8_t*)(*ppReadPackedMsg) < rxBodyEnd && (uint8_t*)(*ppReadPackedMsg) < rxPduEnd) + { + nfapi_tl_t generic_tl; + if( unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_RX_UE_INFORMATION_TAG: + { + pdu = &(value->rx_pdu_list[i++]); + pdu->rx_ue_information.tl = generic_tl; + if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) + return 0; + } + break; + case NFAPI_RX_INDICATION_REL8_TAG: + { + if(pdu != 0) + { + pdu->rx_indication_rel8.tl = generic_tl; + if(unpack_rx_indication_rel8_value(&pdu->rx_indication_rel8, ppReadPackedMsg, end) == 0) + return 0; + + if(pdu->rx_indication_rel8.offset > 0) + { + // Need to check that the data is within the tlv + if(numberOfPdusAddress + pdu->rx_indication_rel8.offset + pdu->rx_indication_rel8.length <= rxBodyEnd) + { + // If this the first pdu set the rxPduEnd + if(numberOfPdusAddress + pdu->rx_indication_rel8.offset < rxPduEnd) + { + rxPduEnd = numberOfPdusAddress + pdu->rx_indication_rel8.offset; + + if(rxPduEnd > end) + { + // pdu end is past buffer end + return 0; + } + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME: the rx data is outside of the tlv\n"); + } + } + } + } + break; + case NFAPI_RX_INDICATION_REL9_TAG: + { + if(pdu != 0) + { + pdu->rx_indication_rel9.tl = generic_tl; + if(unpack_rx_indication_rel9_value(&pdu->rx_indication_rel9, ppReadPackedMsg, end) == 0) + return 0; + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_ULSCH.indication Invalid pdu type %d \n", generic_tl.tag ); + } + break; + } + } + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_pdus; ++idx) + { + if(value->rx_pdu_list[idx].rx_indication_rel8.tl.tag == NFAPI_RX_INDICATION_REL8_TAG) + { + uint32_t length = value->rx_pdu_list[idx].rx_indication_rel8.length; + value->rx_pdu_list[idx].data = nfapi_p7_allocate(length, config); + if(pullarray8(ppReadPackedMsg, value->rx_pdu_list[idx].data, length, length, end) == 0) + { + return 0; + } + } + } + + return 1; +} + +static uint8_t unpack_rx_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_rx_indication_t *pNfapiMsg = (nfapi_rx_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_RX_INDICATION_BODY_TAG, &pNfapiMsg->rx_indication_body, &unpack_rx_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_preamble_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel8_t* preamble_pdu_rel8 = (nfapi_preamble_pdu_rel8_t*)tlv; + + return (pull16(ppReadPackedMsg, &preamble_pdu_rel8->rnti, end) && + pull8(ppReadPackedMsg, &preamble_pdu_rel8->preamble, end) && + pull16(ppReadPackedMsg, &preamble_pdu_rel8->timing_advance, end)); +} + +static uint8_t unpack_preamble_pdu_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel9_t* preamble_pdu_rel9 = (nfapi_preamble_pdu_rel9_t*)tlv; + return pull16(ppReadPackedMsg, &preamble_pdu_rel9->timing_advance_r9, end); +} + +static uint8_t unpack_preamble_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_preamble_pdu_rel13_t* preamble_pdu_rel13 = (nfapi_preamble_pdu_rel13_t*)tlv; + return pull8(ppReadPackedMsg, &preamble_pdu_rel13->rach_resource_type, end); +} + +static uint8_t unpack_rach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_rach_indication_body_t* value = (nfapi_rach_indication_body_t*)tlv; + uint8_t* rachBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(rachBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_preambles, end) == 0) + return 0; + + if(value->number_of_preambles > NFAPI_PREAMBLE_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of preamble du's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_preambles, NFAPI_PREAMBLE_MAX_PDU); + return 0; + } + + if(value->number_of_preambles > 0) + { + value->preamble_list = (nfapi_preamble_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_preamble_pdu_t) * value->number_of_preambles, config); + if(value->preamble_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate preamble pdu list (count:%d)\n", __FUNCTION__, value->number_of_preambles); + return 0; + } + } + else + { + value->preamble_list = 0; + } + + + uint8_t i = 0; + for(i = 0; i < value->number_of_preambles; ++i) + { + nfapi_preamble_pdu_t* pdu = &(value->preamble_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* preamblePduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_PREAMBLE_REL8_TAG, &pdu->preamble_rel8, unpack_preamble_pdu_rel8_value }, + { NFAPI_PREAMBLE_REL9_TAG, &pdu->preamble_rel9, unpack_preamble_pdu_rel9_value }, + { NFAPI_PREAMBLE_REL13_TAG, &pdu->preamble_rel13, unpack_preamble_pdu_rel13_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, preamblePduInstanceEnd, 0, 0) == 0) + return 0; + } + return 1; +} + +static uint8_t unpack_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_rach_indication_t *pNfapiMsg = (nfapi_rach_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_RACH_INDICATION_BODY_TAG, &pNfapiMsg->rach_indication_body, &unpack_rach_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_srs_indication_fdd_rel8_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel8_t* srs_pdu_fdd_rel8 = (nfapi_srs_indication_fdd_rel8_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->doppler_estimation, end) && + pull16(ppReadPackedMsg, &srs_pdu_fdd_rel8->timing_advance, end) && + pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->number_of_resource_blocks, end) && + pull8(ppReadPackedMsg, &srs_pdu_fdd_rel8->rb_start, end) && + pullarray8(ppReadPackedMsg, srs_pdu_fdd_rel8->snr, NFAPI_NUM_RB_MAX, srs_pdu_fdd_rel8->number_of_resource_blocks, end))) + return 0; + return 1; +} + +static uint8_t unpack_srs_indication_fdd_rel9_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel9_t* srs_pdu_fdd_rel9 = (nfapi_srs_indication_fdd_rel9_t*)tlv; + return (pull16(ppReadPackedMsg, &srs_pdu_fdd_rel9->timing_advance_r9, end)); +} + +static uint8_t unpack_srs_indication_tdd_rel10_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_srs_indication_ttd_rel10_t* srs_pdu_tdd_rel10 = (nfapi_srs_indication_ttd_rel10_t*)tlv; + return (pull8(ppReadPackedMsg, &srs_pdu_tdd_rel10->uppts_symbol, end)); +} + +static uint8_t unpack_srs_indication_fdd_rel11_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_srs_indication_fdd_rel11_t* srs_pdu_fdd_rel11 = (nfapi_srs_indication_fdd_rel11_t*)tlv; + return ( pull16(ppReadPackedMsg, &srs_pdu_fdd_rel11->ul_rtoa, end)); +} + +static uint8_t unpack_tdd_channel_measurement_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_tdd_channel_measurement_t* value = (nfapi_tdd_channel_measurement_t*)tlv; + + if(!(pull8(ppReadPackedMsg, &value->num_prb_per_subband, end) && + pull8(ppReadPackedMsg, &value->number_of_subbands, end) && + pull8(ppReadPackedMsg, &value->num_atennas, end))) + return 0; + + if(value->number_of_subbands > NFAPI_MAX_NUM_SUBBANDS) + { + // todo : add error + return 0; + } + + if(value->num_atennas > NFAPI_MAX_NUM_PHYSICAL_ANTENNAS) + { + // todo : add error + return 0; + } + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_subbands; ++idx) + { + if(!(pull8(ppReadPackedMsg, &value->subands[idx].subband_index, end) && + pullarray16(ppReadPackedMsg, value->subands[idx].channel, NFAPI_MAX_NUM_PHYSICAL_ANTENNAS, value->num_atennas, end))) + return 0; + } + + return 1; +} + + +static uint8_t unpack_srs_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_srs_indication_body_t* value = (nfapi_srs_indication_body_t*)tlv; + uint8_t* srsBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(srsBodyEnd > end) + return 0; + + if(pull8(ppReadPackedMsg, &value->number_of_ues, end) == 0) + return 0; + + if(value->number_of_ues > NFAPI_SRS_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of srs ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_ues, NFAPI_SRS_IND_MAX_PDU); + return 0; + } + + if(value->number_of_ues > 0) + { + value->srs_pdu_list = (nfapi_srs_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_srs_indication_pdu_t) * value->number_of_ues, config); + if(value->srs_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate srs ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_ues); + return 0; + } + } + else + { + value->srs_pdu_list = 0; + } + + + + uint8_t i = 0; + for(i = 0; i < value->number_of_ues; ++i) + { + nfapi_srs_indication_pdu_t* pdu = &(value->srs_pdu_list[i]); + + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* srsPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_SRS_INDICATION_FDD_REL8_TAG, &pdu->srs_indication_fdd_rel8, unpack_srs_indication_fdd_rel8_value}, + { NFAPI_SRS_INDICATION_FDD_REL9_TAG, &pdu->srs_indication_fdd_rel9, unpack_srs_indication_fdd_rel9_value}, + { NFAPI_SRS_INDICATION_TDD_REL10_TAG, &pdu->srs_indication_tdd_rel10, unpack_srs_indication_tdd_rel10_value}, + { NFAPI_SRS_INDICATION_FDD_REL11_TAG, &pdu->srs_indication_fdd_rel11, unpack_srs_indication_fdd_rel11_value}, + { NFAPI_TDD_CHANNEL_MEASUREMENT_TAG, &pdu->tdd_channel_measurement, unpack_tdd_channel_measurement_value}, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srsPduInstanceEnd, 0, 0) == 0) + return 0; + } + return 1; +} + +static uint8_t unpack_srs_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_srs_indication_t *pNfapiMsg = (nfapi_srs_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_SRS_INDICATION_BODY_TAG, &pNfapiMsg->srs_indication_body, &unpack_srs_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_sr_indication_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_sr_indication_body_t* value = (nfapi_sr_indication_body_t*)tlv; + uint8_t* srBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(srBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_srs, end) == 0) + return 0; + + if(value->number_of_srs > NFAPI_SR_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of sr ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_srs, NFAPI_SR_IND_MAX_PDU); + return 0; + } + + if(value->number_of_srs > 0) + { + value->sr_pdu_list = (nfapi_sr_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_sr_indication_pdu_t) * value->number_of_srs, config); + if(value->sr_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate sr ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_srs); + return 0; + } + } + else + { + value->sr_pdu_list = 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_srs; ++i) + { + nfapi_sr_indication_pdu_t* pdu = &(value->sr_pdu_list[i]); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* srPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, unpack_ul_cqi_information_value }, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, srPduInstanceEnd, 0, 0) == 0) + return 0; + } + + return 1; + +} + +static int unpack_sr_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_sr_indication_t *pNfapiMsg = (nfapi_sr_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_SR_INDICATION_BODY_TAG, &pNfapiMsg->sr_indication_body, &unpack_sr_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_cqi_indication_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_rel8_t* cqi_pdu_rel8 = (nfapi_cqi_indication_rel8_t*)tlv; + + return (pull16(ppReadPackedMsg, &cqi_pdu_rel8->length, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel8->data_offset, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel8->ul_cqi, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel8->ri, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel8->timing_advance, end)); + +} + +static uint8_t unpack_cqi_indication_rel9_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_cqi_indication_rel9_t* cqi_pdu_rel9 = (nfapi_cqi_indication_rel9_t*)tlv; + + if(!(pull16(ppReadPackedMsg, &cqi_pdu_rel9->length, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->data_offset, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel9->ul_cqi, end) && + pull8(ppReadPackedMsg, &cqi_pdu_rel9->number_of_cc_reported, end))) + return 0; + + if(cqi_pdu_rel9->number_of_cc_reported > NFAPI_CC_MAX) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : out of bound array\n"); + return 0; + } + + if(!(pullarray8(ppReadPackedMsg, cqi_pdu_rel9->ri, NFAPI_CC_MAX, cqi_pdu_rel9->number_of_cc_reported, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance, end) && + pull16(ppReadPackedMsg, &cqi_pdu_rel9->timing_advance_r9, end))) + return 0; + + return 1; +} + +static uint8_t unpack_cqi_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_cqi_indication_body_t* value = (nfapi_cqi_indication_body_t*)tlv; + + // the cqiBodyEnd points to the end of the cqi PDU's + uint8_t* cqiBodyEnd = *ppReadPackedMsg + value->tl.length; + + //uint8_t* cqiPduEnd = cqiBodyEnd; + //uint8_t* numberOfPdusAddress = *ppReadPackedMsg; + + if(cqiBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_cqis, end) == 0) + return 0; + + if(value->number_of_cqis > NFAPI_CQI_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of cqi ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_cqis, NFAPI_CQI_IND_MAX_PDU); + return -1; + } + + if(value->number_of_cqis > 0) + { + value->cqi_pdu_list = (nfapi_cqi_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_pdu_t) * value->number_of_cqis, config); + if(value->cqi_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); + return 0; + } + } + else + { + value->cqi_pdu_list = 0; + } + + if(value->number_of_cqis > 0) + { + value->cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_cqi_indication_raw_pdu_t) * value->number_of_cqis, config); + if(value->cqi_raw_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate raw cqi ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_cqis); + return 0; + } + } + else + { + value->cqi_raw_pdu_list = 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_cqis; ++i) + { + nfapi_cqi_indication_pdu_t* pdu = &(value->cqi_pdu_list[i]); + memset(pdu, 0, sizeof(nfapi_cqi_indication_pdu_t)); + + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* cqiPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + + while((uint8_t*)(*ppReadPackedMsg) < cqiPduInstanceEnd) + { + nfapi_tl_t generic_tl; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_RX_UE_INFORMATION_TAG: + pdu->rx_ue_information.tl = generic_tl; + if(unpack_rx_ue_information_value(&pdu->rx_ue_information, ppReadPackedMsg, end) == 0) + return 0; + break; + case NFAPI_CQI_INDICATION_REL8_TAG: + pdu->cqi_indication_rel8.tl = generic_tl; + if(unpack_cqi_indication_rel8_value(&pdu->cqi_indication_rel8, ppReadPackedMsg, end) == 0) + return 0; + + break; + case NFAPI_CQI_INDICATION_REL9_TAG: + pdu->cqi_indication_rel9.tl = generic_tl; + if(unpack_cqi_indication_rel9_value(&pdu->cqi_indication_rel9, ppReadPackedMsg, end) == 0) + return 0; + + break; + case NFAPI_UL_CQI_INFORMATION_TAG: + pdu->ul_cqi_information.tl = generic_tl; + if(unpack_ul_cqi_information_value(&pdu->ul_cqi_information, ppReadPackedMsg, end) == 0) + return 0; + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "RX_CQI.indication Invalid pdu type %d \n", generic_tl.tag ); + } + break; + + }; + } + } + + uint8_t idx = 0; + for(idx = 0; idx < value->number_of_cqis; ++idx) + { + if(value->cqi_pdu_list[idx].cqi_indication_rel8.tl.tag == NFAPI_CQI_INDICATION_REL8_TAG) + { + if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel8.length, end) == 0) + return 0; + } + else if(value->cqi_pdu_list[idx].cqi_indication_rel9.tl.tag == NFAPI_CQI_INDICATION_REL9_TAG) + { + if(pullarray8(ppReadPackedMsg, &(value->cqi_raw_pdu_list[idx].pdu[0]), NFAPI_CQI_RAW_MAX_LEN, value->cqi_pdu_list[idx].cqi_indication_rel9.length, end) == 0) + return 0; + } + } + + + return 1; + +} + +static uint8_t unpack_cqi_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_cqi_indication_t *pNfapiMsg = (nfapi_cqi_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_CQI_INDICATION_BODY_TAG, &pNfapiMsg->cqi_indication_body, &unpack_cqi_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_lbt_pdsch_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_lbt_pdsch_req_pdu_rel13_t* value = (nfapi_lbt_pdsch_req_pdu_rel13_t*)tlv; + + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->mp_cca, end) && + pull32(ppReadPackedMsg, &value->n_cca, end) && + pull32(ppReadPackedMsg, &value->offset, end) && + pull32(ppReadPackedMsg, &value->lte_txop_sf, end) && + pull16(ppReadPackedMsg, &value->txop_sfn_sf_end, end) && + pull32(ppReadPackedMsg, &value->lbt_mode, end)); +} + +static uint8_t unpack_lbt_drs_req_pdu_rel13_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_lbt_drs_req_pdu_rel13_t* value = (nfapi_lbt_drs_req_pdu_rel13_t*)tlv; + + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->offset, end) && + pull16(ppReadPackedMsg, &value->sfn_sf_end, end) && + pull32(ppReadPackedMsg, &value->lbt_mode, end)); +} + + +static uint8_t unpack_lbt_config_request_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_config_request_body_t* value = (nfapi_lbt_dl_config_request_body_t*)tlv; + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl config pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU); + return 0; + } + + if(value->number_of_pdus) + { + value->lbt_dl_config_req_pdu_list = (nfapi_lbt_dl_config_request_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_config_request_pdu_t) * value->number_of_pdus, config); + if(value->lbt_dl_config_req_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } + else + { + value->lbt_dl_config_req_pdu_list = 0; + } + + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_lbt_dl_config_request_pdu_t* pdu = &(value->lbt_dl_config_req_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG, &pdu->lbt_pdsch_req_pdu.lbt_pdsch_req_pdu_rel13, &unpack_lbt_pdsch_req_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_LBT_DRS_REQ_PDU_REL13_TAG, &pdu->lbt_drs_req_pdu.lbt_drs_req_pdu_rel13, &unpack_lbt_drs_req_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL_CONFIG.request body invalid pdu type %d\n", pdu->pdu_type); + return 0; + } + } + + return 1; +} +static uint8_t unpack_lbt_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_config_request_t *pNfapiMsg = (nfapi_lbt_dl_config_request_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG, &pNfapiMsg->lbt_dl_config_request_body, &unpack_lbt_config_request_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_lbt_pdsch_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_lbt_pdsch_rsp_pdu_rel13_t* value = (nfapi_lbt_pdsch_rsp_pdu_rel13_t*)tlv; + + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->result, end) && + pull32(ppReadPackedMsg, &value->lte_txop_symbols, end) && + pull32(ppReadPackedMsg, &value->initial_partial_sf, end)); + +} +static uint8_t unpack_lbt_drs_rsp_pdu_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_lbt_drs_rsp_pdu_rel13_t* value = (nfapi_lbt_drs_rsp_pdu_rel13_t*)tlv; + + return (pull32(ppReadPackedMsg, &value->handle, end) && + pull32(ppReadPackedMsg, &value->result, end)); +} + +static uint8_t unpack_lbt_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_indication_body_t* value = (nfapi_lbt_dl_indication_body_t*)tlv; + + if(pull16(ppReadPackedMsg, &value->number_of_pdus, end) == 0) + return 0; + + if(value->number_of_pdus > NFAPI_LBT_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of lbt dl ind pdu's exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_pdus, NFAPI_LBT_IND_MAX_PDU); + return 0; + } + + if(value->number_of_pdus > 0) + { + value->lbt_indication_pdu_list = (nfapi_lbt_dl_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_lbt_dl_indication_pdu_t) * value->number_of_pdus, config); + if(value->lbt_indication_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate lbt dl ind config pdu list (count:%d)\n", __FUNCTION__, value->number_of_pdus); + return 0; + } + } + else + { + value->lbt_indication_pdu_list = 0; + } + + uint16_t i; + uint16_t total_number_of_pdus = value->number_of_pdus; + for(i = 0; i < total_number_of_pdus; ++i) + { + nfapi_lbt_dl_indication_pdu_t* pdu = &(value->lbt_indication_pdu_list[i]); + + if(!(pull8(ppReadPackedMsg, &pdu->pdu_type, end) && + pull8(ppReadPackedMsg, &pdu->pdu_size, end))) + return 0; + + uint8_t *packedPduEnd = (*ppReadPackedMsg) + pdu->pdu_size - 2; + + if(packedPduEnd > end) + return 0; + + switch(pdu->pdu_type) + { + case NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG, &pdu->lbt_pdsch_rsp_pdu.lbt_pdsch_rsp_pdu_rel13, &unpack_lbt_pdsch_rsp_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + case NFAPI_LBT_DL_RSP_DRS_PDU_TYPE: + { + unpack_tlv_t unpack_fns[] = + { + { NFAPI_LBT_DRS_RSP_PDU_REL13_TAG, &pdu->lbt_drs_rsp_pdu.lbt_drs_rsp_pdu_rel13, &unpack_lbt_drs_rsp_pdu_rel13_value}, + }; + + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, packedPduEnd, 0, 0); + } + break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "LBT_DL.indication body invalid pdu type %d\n", pdu->pdu_type); + return 0; + } + } + + return 1; +} +static uint8_t unpack_lbt_dl_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_lbt_dl_indication_t *pNfapiMsg = (nfapi_lbt_dl_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_LBT_DL_INDICATION_BODY_TAG, &pNfapiMsg->lbt_dl_indication_body, &unpack_lbt_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nb_harq_indication_fdd_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nb_harq_indication_fdd_rel13_t* value = (nfapi_nb_harq_indication_fdd_rel13_t*)tlv; + return (pull8(ppReadPackedMsg, &value->harq_tb1, end)); +} + + +static uint8_t unpack_nb_harq_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nb_harq_indication_body_t* value = (nfapi_nb_harq_indication_body_t*)tlv; + uint8_t* nbharqBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(nbharqBodyEnd > end) + return 0; + + if(pull16(ppReadPackedMsg, &value->number_of_harqs, end) == 0) + return 0; + + if(value->number_of_harqs > NFAPI_HARQ_IND_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of harq ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_harqs, NFAPI_HARQ_IND_MAX_PDU); + return 0; + } + + value->nb_harq_pdu_list = (nfapi_nb_harq_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nb_harq_indication_pdu_t) * value->number_of_harqs, config); + if(value->nb_harq_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate harq ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_harqs); + return 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_harqs; ++i) + { + nfapi_nb_harq_indication_pdu_t* pdu = &(value->nb_harq_pdu_list[i]); + if(pull16(ppReadPackedMsg, &pdu->instance_length, end) == 0) + return 0; + + uint8_t* harqPduInstanceEnd = *ppReadPackedMsg + pdu->instance_length; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_RX_UE_INFORMATION_TAG, &pdu->rx_ue_information, unpack_rx_ue_information_value }, + { NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG, &pdu->nb_harq_indication_fdd_rel13, &unpack_nb_harq_indication_fdd_rel13_value}, + { NFAPI_UL_CQI_INFORMATION_TAG, &pdu->ul_cqi_information, &unpack_ul_cqi_information_value} + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, harqPduInstanceEnd, 0, 0) == 0) + return 0; + + } + + return 1; +} + +static uint8_t unpack_nb_harq_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nb_harq_indication_t *pNfapiMsg = (nfapi_nb_harq_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_NB_HARQ_INDICATION_BODY_TAG, &pNfapiMsg->nb_harq_indication_body, &unpack_nb_harq_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nrach_indication_pdu_rel13_t* value = (nfapi_nrach_indication_pdu_rel13_t*)tlv; + + return (pull16(ppReadPackedMsg, &value->rnti, end) && + pull8(ppReadPackedMsg, &value->initial_sc, end) && + pull16(ppReadPackedMsg, &value->timing_advance, end) && + pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); +} + +static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; + if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){ + return 0; + } + else{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); + } + return 1; +} + +static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; + uint8_t* nrachBodyEnd = *ppReadPackedMsg + value->tl.length; + + if(nrachBodyEnd > end) + return 0; + + if(pull8(ppReadPackedMsg, &value->number_of_initial_scs_detected, end) == 0) + return 0; + + if(value->number_of_initial_scs_detected > NFAPI_PREAMBLE_MAX_PDU) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of detected scs ind pdus exceed maxium (count:%d max:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected, NFAPI_PREAMBLE_MAX_PDU); + return 0; + } + + value->nrach_pdu_list = (nfapi_nrach_indication_pdu_t*)nfapi_p7_allocate(sizeof(nfapi_nrach_indication_pdu_t) * value->number_of_initial_scs_detected, config); + if(value->nrach_pdu_list == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s failed to allocate nrach ind pdu list (count:%d)\n", __FUNCTION__, value->number_of_initial_scs_detected); + return 0; + } + + uint8_t i = 0; + for(i = 0; i < value->number_of_initial_scs_detected; ++i) + { + nfapi_nrach_indication_pdu_t* pdu = &(value->nrach_pdu_list[i]); + + uint8_t* nrachPduInstanceEnd = *ppReadPackedMsg + 4 + 6; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_NRACH_INDICATION_REL13_TAG, &pdu->nrach_indication_rel13, &unpack_nrach_indication_rel13_value}, + }; + + if(unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, nrachPduInstanceEnd, 0, 0) == 0) + return 0; + + } + + return 1; +} + +static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nrach_indication_t *pNfapiMsg = (nfapi_nrach_indication_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + { NFAPI_NRACH_INDICATION_BODY_TAG, &pNfapiMsg->nrach_indication_body, &unpack_nrach_indication_body_value}, + }; + + return (pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_nr_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_slot, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_sf, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_nr_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + +static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_config_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_config_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_config_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->hi_dci0_earliest_arrival, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + +static uint8_t unpack_nr_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->last_slot, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_dci_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_earliest_arrival, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + + +// unpack length check + +static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) +{ + int retLen = 0; + + switch (msgId) + { + case NFAPI_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_dl_config_request_t)) + retLen = sizeof(nfapi_dl_config_request_t); + break; + + case NFAPI_UL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ul_config_request_t)) + retLen = sizeof(nfapi_ul_config_request_t); + break; + + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); + break; + + case NFAPI_HI_DCI0_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_hi_dci0_request_t)) + retLen = sizeof(nfapi_hi_dci0_request_t); + break; + + case NFAPI_TX_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_tx_request_t)) + retLen = sizeof(nfapi_tx_request_t); + break; + + case NFAPI_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) + retLen = sizeof(nfapi_harq_indication_t); + break; + + case NFAPI_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) + retLen = sizeof(nfapi_crc_indication_t); + break; + + case NFAPI_RX_ULSCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) + retLen = sizeof(nfapi_rx_indication_t); + break; + + case NFAPI_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) + retLen = sizeof(nfapi_rach_indication_t); + break; + + case NFAPI_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) + retLen = sizeof(nfapi_srs_indication_t); + break; + + case NFAPI_RX_SR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) + retLen = sizeof(nfapi_sr_indication_t); + break; + + case NFAPI_RX_CQI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) + retLen = sizeof(nfapi_cqi_indication_t); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) + retLen = sizeof(nfapi_lbt_dl_config_request_t); + break; + + case NFAPI_LBT_DL_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) + retLen = sizeof(nfapi_lbt_dl_indication_t); + break; + + case NFAPI_NB_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) + retLen = sizeof(nfapi_nb_harq_indication_t); + break; + + case NFAPI_NRACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) + retLen = sizeof(nfapi_nrach_indication_t); + break; + + case NFAPI_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_dl_node_sync_t)) + retLen = sizeof(nfapi_dl_node_sync_t); + break; + + case NFAPI_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_ul_node_sync_t)) + retLen = sizeof(nfapi_ul_node_sync_t); + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; +} + +static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) +{ + int retLen = 0; + + switch (msgId) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) + retLen = sizeof(nfapi_nr_dl_tti_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) + retLen = sizeof(nfapi_nr_ul_tti_request_t); + break; + + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) + retLen = sizeof(nfapi_nr_ul_dci_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) + retLen = sizeof(nfapi_nr_tx_data_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rx_data_indication_t)) + retLen = sizeof(nfapi_nr_rx_data_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_crc_indication_t)) + retLen = sizeof(nfapi_nr_crc_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_rach_indication_t)) + retLen = sizeof(nfapi_nr_rach_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_uci_indication_t)) + retLen = sizeof(nfapi_nr_uci_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nr_srs_indication_t)) + retLen = sizeof(nfapi_nr_srs_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) + retLen = sizeof(nfapi_nr_dl_node_sync_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) + retLen = sizeof(nfapi_nr_ul_node_sync_t); + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; +} + + + +// Main unpack functions - public + +int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +{ + nfapi_p7_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 header unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + return -1; + + return 0; +} + +int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +{ + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + /* + uint8_t *ptr = pMessageBuf; + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); +*/ + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } + + if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); + return -1; + } + + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ + + // look for the specific message + switch (pMessageHeader->message_id) + { + case NFAPI_DL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_UL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_ul_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_TX_REQUEST: + if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) + result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_HI_DCI0_REQUEST: + if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) + result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_HARQ_INDICATION: + if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_CRC_INDICATION: + if (check_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) + result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_ULSCH_INDICATION: + if (check_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RACH_INDICATION: + if (check_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_SRS_INDICATION: + if (check_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_SR_INDICATION: + if (check_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_CQI_INDICATION: + if (check_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (check_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_INDICATION: + if (check_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NB_HARQ_INDICATION: + if (check_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NRACH_INDICATION: + if (check_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_DL_NODE_SYNC: + if (check_unpack_length(NFAPI_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UL_NODE_SYNC: + if (check_unpack_length(NFAPI_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_TIMING_INFO: + if (check_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + default: + + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->unpack_p7_vendor_extension) + { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } + + if(result == 0) + return -1; + else + return 0; +} + +int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +{ + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + // uint8_t *ptr = pMessageBuf; + // printf("\n Read P7 message unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); + + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } + + if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); + return -1; + } + + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ + + // look for the specific message + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) + result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) + result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) + result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) + result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) + result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) + result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) + result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) + result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_TIMING_INFO: + if (check_nr_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + default: + + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->unpack_p7_vendor_extension) + { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } + + if(result == 0) + return -1; + else + return 0; +} + + diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 8520a5d162..fc9cd66077 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -27,6 +27,7 @@ extern "C" { #include #include "nfapi_nr_interface.h" #include "nfapi_nr_interface_scf.h" + #include #include "openair1/PHY/defs_gNB.h" diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 3511ed2fb9..ab3b9196f1 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -937,7 +937,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); pnf_p7->sfn = sfn; - pnf_p7->slot = slot; + pnf_p7->slot = slot; @@ -1559,6 +1559,9 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, // } // } + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + printf("PNF SFN:%d, PNF slot:%d, VNF SFN:%d, VNF slot:%d, Curr time;%d.%d. \n",phy->sfn,phy->slot,sfn,slot,curr_time.tv_sec,curr_time.tv_nsec); if(current_sfn_slot_dec <= recv_sfn_slot_dec + timing_window){ in_window = 1; NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); @@ -1571,8 +1574,8 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, else { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); + }//Need to add more cases @@ -3202,6 +3205,8 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) { + uint16_t pnf_frame = 0; + uint8_t pnf_slot = 0; // initialize the mutex lock if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) { @@ -3284,8 +3289,8 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) FD_SET(pnf_p7->p7_sock, &rfds); struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; + timeout.tv_sec = 0; + timeout.tv_usec = 500; selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout); @@ -3297,7 +3302,15 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(selectRetval == 0) { // timeout - continue; + //continue; + if (pnf_slot == 19) + pnf_frame = (pnf_frame + 1) % 1024; + pnf_slot = (pnf_slot + 1) % 20; + pnf_p7->sfn = pnf_frame; + pnf_p7->slot = pnf_slot; + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",pnf_p7->sfn,pnf_p7->slot,curr_time.tv_sec,curr_time.tv_nsec); } else if (selectRetval == -1 && (errno == EINTR)) { @@ -3315,7 +3328,7 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(FD_ISSET(pnf_p7->p7_sock, &rfds)) { - pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); + pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); } } NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index efcb60ce96..88aa1391cb 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -175,17 +175,7 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t pnf_p7_t* _this = (pnf_p7_t*)(config); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); } -int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) -{ - if(config == NULL || ind == NULL) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); - return -1; - } - pnf_p7_t* _this = (pnf_p7_t*)(config); - return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); -} int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) { if(config == NULL || ind == NULL) @@ -265,3 +255,65 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re return pnf_p7_pack_and_send_p7_message(_this, &(resp->header), sizeof(nfapi_ue_release_response_t)); } + +//NR UPLINK INDICATION + +int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); +} + +int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_crc_indication_t)); +} + +int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_srs_indication_t)); +} + +int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_uci_indication_t)); +} + +int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rach_indication_t)); +} diff --git a/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp b/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp index 4fe5065cea..1c2f0bef80 100644 --- a/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp +++ b/nfapi/open-nFAPI/pnf_sim/src/fapi_stub.cpp @@ -278,7 +278,7 @@ void *fapi_thread_start(void *ptr) { if(instance->tick == 1000) { if(instance->tx_byte_count > 0) { - printf("[FAPI] Tx rate %u bytes/sec\n", instance->tx_byte_count); + printf("[FAPI] Tx rate %d bytes/sec\n", instance->tx_byte_count); instance->tx_byte_count = 0; } @@ -319,7 +319,7 @@ void *fapi_thread_start(void *ptr) { millisec = now_ts.tv_nsec / 1e6; if(last_millisec != -1 && ((last_millisec + 1 ) % 1000) != millisec) { - printf("*** missing millisec %u %u\n", last_millisec, millisec); + printf("*** missing millisec %d %d\n", last_millisec, millisec); catchup = millisec - last_millisec - 1; } diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index 248faf8369..ad1c5e7944 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -24,6 +24,8 @@ #define TIMEHR_USEC(_time_hr) ((uint32_t)(_time_hr) & 0xFFFFF) #define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF)) + + typedef struct { uint8_t* buffer; uint16_t length; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 39f7899d77..936c434f44 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -461,6 +461,7 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno); } + return 0; } @@ -676,6 +677,7 @@ int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_inf //dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr); dl_node_sync.t1 = calculate_nr_t1(p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr); dl_node_sync.delta_sfn_slot = 0; + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header); } @@ -1451,8 +1453,102 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) phy->previous_t1 = ind.t1; phy->previous_t2 = ind.t2; } +} +//NR HANDLES FOR UPLINK MESSAGES +void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_rx_data_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_crc_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_srs_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } +} + +void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_uci_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + } +} + +void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_rach_indication_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + + } } void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) @@ -1485,358 +1581,368 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 // divide by 2 using shift operator uint32_t latency = (tx_2_rx - pnf_proc_time) >> 1; - if(!(phy->filtered_adjust)) + if(phy->in_sync == 0) { - phy->latency[phy->min_sync_cycle_count] = latency; - - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", - // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, - // tx_2_rx, pnf_proc_time, latency); - } - else - { - phy->latency[phy->min_sync_cycle_count] = latency; - - //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) - { - if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) - { - // Only t2 wrap has occurred!!! - phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; - } - else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) - { - // Only t1 wrap has occurred - phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; - } - else - { - // Either no wrap or both have wrapped - phy->slot_offset = ind.t2 - ind.t1 - latency; - } - - if (phy->slot_offset_filtered == 0) - { - phy->slot_offset_filtered = phy->slot_offset; - } - else - { - int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; - int32_t newOffsetShifted = phy->slot_offset << 5; - - // 1/8 of new and 7/8 of old - phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; - } - } - - if(1) - { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", - // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, - // ind.t1, ind.t2, ind.t3, t4, - // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, - // (ind.t1previous_t1), (ind.t2previous_t2)); - } + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + if(vnf_p7->_public.sync_indication) + (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); } - if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) - { - phy->filtered_adjust = 0; - phy->zero_count=0; - phy->min_sync_cycle_count = 2; - phy->in_sync = 0; - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); - } + phy->in_sync = 1; - if(phy->min_sync_cycle_count) - phy->min_sync_cycle_count--; + // if(!(phy->filtered_adjust)) + // { + // phy->latency[phy->min_sync_cycle_count] = latency; - if(phy->min_sync_cycle_count == 0) - { - uint32_t curr_sfn = phy->sfn; - uint32_t curr_slot = phy->slot; - int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", + // // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, + // // tx_2_rx, pnf_proc_time, latency); + // } + // else + // { + // phy->latency[phy->min_sync_cycle_count] = latency; - if(!phy->filtered_adjust) - { - int i = 0; - //phy->average_latency = 0; - for(i = 0; i < SYNC_CYCLE_COUNT; ++i) - { - phy->average_latency += phy->latency[i]; + // //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) + // { + // if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) + // { + // // Only t2 wrap has occurred!!! + // phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; + // } + // else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) + // { + // // Only t1 wrap has occurred + // phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; + // } + // else + // { + // // Either no wrap or both have wrapped + // phy->slot_offset = ind.t2 - ind.t1 - latency; + // } - } - phy->average_latency /= SYNC_CYCLE_COUNT; + // if (phy->slot_offset_filtered == 0) + // { + // phy->slot_offset_filtered = phy->slot_offset; + // } + // else + // { + // int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; + // int32_t newOffsetShifted = phy->slot_offset << 5; - phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); + // // 1/8 of new and 7/8 of old + // phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; + // } + // } - sfn_slot_dec += (phy->slot_offset / 500); + // if(1) + // { + // struct timespec ts; + // clock_gettime(CLOCK_MONOTONIC, &ts); + + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + // // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + // // ind.t1, ind.t2, ind.t3, t4, + // // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + // // (ind.t1previous_t1), (ind.t2previous_t2)); + // } + + // } + + // if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) + // { + // phy->filtered_adjust = 0; + // phy->zero_count=0; + // phy->min_sync_cycle_count = 2; + // phy->in_sync = 0; + // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); + // } + + // if(phy->min_sync_cycle_count) + // phy->min_sync_cycle_count--; + + // if(phy->min_sync_cycle_count == 0) + // { + // uint32_t curr_sfn = phy->sfn; + // uint32_t curr_slot = phy->slot; + // int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + + // if(!phy->filtered_adjust) + // { + // int i = 0; + // //phy->average_latency = 0; + // for(i = 0; i < SYNC_CYCLE_COUNT; ++i) + // { + // phy->average_latency += phy->latency[i]; + + // } + // phy->average_latency /= SYNC_CYCLE_COUNT; + + // phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); + + // sfn_slot_dec += (phy->slot_offset / 500); - NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); - } - else - { - sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot + // } + // else + // { + // sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot - } + // } - if(sfn_slot_dec < 0) - { - sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; - } - else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) - { - sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; - } + // if(sfn_slot_dec < 0) + // { + // sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; + // } + // else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) + // { + // sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; + // } - uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); - uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); + // uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); + // uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); - { - phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); + // { + // phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); - phy->previous_t1 = 0; - phy->previous_t2 = 0; +// phy->previous_t1 = 0; +// phy->previous_t2 = 0; - if(phy->previous_slot_offset_filtered > 0) - { - if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) - { - // pnf is getting futher ahead of vnf - //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; - phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; - } - else - { - // pnf is getting back in sync - } - } - else if(phy->previous_slot_offset_filtered < 0) - { - if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) - { - // vnf is getting future ahead of pnf - //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); - phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; - } - else - { - // vnf is getting back in sync - } - } +// if(phy->previous_slot_offset_filtered > 0) +// { +// if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) +// { +// // pnf is getting futher ahead of vnf +// //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; +// phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; +// } +// else +// { +// // pnf is getting back in sync +// } +// } +// else if(phy->previous_slot_offset_filtered < 0) +// { +// if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) +// { +// // vnf is getting future ahead of pnf +// //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); +// phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; +// } +// else +// { +// // vnf is getting back in sync +// } +// } - int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; - int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; +// int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; +// int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; - if(insync_minor_adjustment_1 == 0) - insync_minor_adjustment_1 = 2; +// if(insync_minor_adjustment_1 == 0) +// insync_minor_adjustment_1 = 2; - if(insync_minor_adjustment_2 == 0) - insync_minor_adjustment_2 = 10; +// if(insync_minor_adjustment_2 == 0) +// insync_minor_adjustment_2 = 10; - if(!phy->filtered_adjust) - { - if(phy->adjustment < 10) - { - phy->zero_count++; +// if(!phy->filtered_adjust) +// { +// if(phy->adjustment < 10) +// { +// phy->zero_count++; - if(phy->zero_count >= 10) - { - phy->filtered_adjust = 1; - phy->zero_count = 0; +// if(phy->zero_count >= 10) +// { +// phy->filtered_adjust = 1; +// phy->zero_count = 0; - NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); - } - } - else - { - phy->zero_count = 0; - } - } - else - { - // Fine level of adjustment - if (phy->adjustment == 0) - { - if (phy->zero_count >= 10) - { - if(phy->in_sync == 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); +// NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); +// } +// } +// else +// { +// phy->zero_count = 0; +// } +// } +// else +// { +// // Fine level of adjustment +// if (phy->adjustment == 0) +// { +// if (phy->zero_count >= 10) +// { +// if(phy->in_sync == 0) +// { +// NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); - if(vnf_p7->_public.sync_indication) - (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); - } +// if(vnf_p7->_public.sync_indication) +// (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); +// } - phy->in_sync = 1; - } - else - { - phy->zero_count++; - } +// phy->in_sync = 1; +// } +// else +// { +// phy->zero_count++; +// } - if(phy->in_sync) - { - // in sync - if(phy->slot_offset_filtered > 250) - { - // VNF is slow - phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; - phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); - } - else if(phy->slot_offset_filtered < -250) - { - // VNF is fast - phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; - phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); - } - else - { - phy->insync_minor_adjustment = 0; - } +// if(phy->in_sync) +// { +// // in sync +// if(phy->slot_offset_filtered > 250) +// { +// // VNF is slow +// phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; +// phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); +// } +// else if(phy->slot_offset_filtered < -250) +// { +// // VNF is fast +// phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; +// phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); +// } +// else +// { +// phy->insync_minor_adjustment = 0; +// } - if(phy->insync_minor_adjustment != 0) - { - // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", - // phy->sfn, phy->slot, ind.header.phy_id, - // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, - // phy->slot_offset_filtered, - // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, - // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), - // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), - // phy->adjustment); - } - } - } - else - { - if (phy->in_sync) - { - if(phy->adjustment == 0) - { - } - else if(phy->adjustment > 0) - { - // VNF is slow - //if(phy->adjustment == 1) - { - // - if(phy->slot_offset_filtered > 250) - { - // VNF is slow - phy->insync_minor_adjustment = insync_minor_adjustment_2; - phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); - } - else if(phy->slot_offset_filtered < -250) - { - // VNF is fast - phy->insync_minor_adjustment = -(insync_minor_adjustment_2); - phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); - } +// if(phy->insync_minor_adjustment != 0) +// { +// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", +// // phy->sfn, phy->slot, ind.header.phy_id, +// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, +// // phy->slot_offset_filtered, +// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, +// // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), +// // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), +// // phy->adjustment); +// } +// } +// } +// else +// { +// if (phy->in_sync) +// { +// if(phy->adjustment == 0) +// { +// } +// else if(phy->adjustment > 0) +// { +// // VNF is slow +// //if(phy->adjustment == 1) +// { +// // +// if(phy->slot_offset_filtered > 250) +// { +// // VNF is slow +// phy->insync_minor_adjustment = insync_minor_adjustment_2; +// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); +// } +// else if(phy->slot_offset_filtered < -250) +// { +// // VNF is fast +// phy->insync_minor_adjustment = -(insync_minor_adjustment_2); +// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); +// } - } - //else - { - // out of sync? - } +// } +// //else +// { +// // out of sync? +// } - // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", - // phy->sfn, phy->slot, ind.header.phy_id, - // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, - // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, - // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), - // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), - // phy->adjustment); +// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", +// // phy->sfn, phy->slot, ind.header.phy_id, +// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, +// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, +// // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), +// // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), +// // phy->adjustment); - } - else if(phy->adjustment < 0) - { - // VNF is fast - //if(phy->adjustment == -1) - { - // - if(phy->slot_offset_filtered > 250) - { - // VNF is slow - phy->insync_minor_adjustment = insync_minor_adjustment_2; - phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); - } - else if(phy->slot_offset_filtered < -250) - { - // VNF is fast - phy->insync_minor_adjustment = -(insync_minor_adjustment_2); - phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); - } - } - //else - { - // out of sync? - } +// } +// else if(phy->adjustment < 0) +// { +// // VNF is fast +// //if(phy->adjustment == -1) +// { +// // +// if(phy->slot_offset_filtered > 250) +// { +// // VNF is slow +// phy->insync_minor_adjustment = insync_minor_adjustment_2; +// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); +// } +// else if(phy->slot_offset_filtered < -250) +// { +// // VNF is fast +// phy->insync_minor_adjustment = -(insync_minor_adjustment_2); +// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); +// } +// } +// //else +// { +// // out of sync? +// } - // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", - // phy->sfn, phy->slot, ind.header.phy_id, - // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, - // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); - } +// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", +// // phy->sfn, phy->slot, ind.header.phy_id, +// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, +// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); +// } - /* - if (phy->adjustment > 10 || phy->adjustment < -10) - { - phy->zero_count++; // Add one to the getting out of sync counter - } - else - { - phy->zero_count = 0; // Small error - zero the out of sync counter - } +// /* +// if (phy->adjustment > 10 || phy->adjustment < -10) +// { +// phy->zero_count++; // Add one to the getting out of sync counter +// } +// else +// { +// phy->zero_count = 0; // Small error - zero the out of sync counter +// } - if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); - //pP7SockInfo->syncAchieved = 0; - } - */ - } - } - } +// if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync +// { +// NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); +// //pP7SockInfo->syncAchieved = 0; +// } +// */ +// } +// } +// } - if(phy->in_sync == 0) - { - /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", - ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), - NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, - phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", - phy->zero_count, - phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ +// if(phy->in_sync == 0) +// { +// /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", +// ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), +// NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, +// phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", +// phy->zero_count, +// phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ - phy->sfn = new_sfn; - phy->slot = new_slot; - } - } +// phy->sfn = new_sfn; +// phy->slot = new_slot; +// } +// } - // reset for next cycle - phy->previous_slot_offset_filtered = phy->slot_offset_filtered; - phy->min_sync_cycle_count = 2; - phy->slot_offset_filtered = 0; - phy->slot_offset = 0; - } - else - { - phy->previous_t1 = ind.t1; - phy->previous_t2 = ind.t2; - } -} +// // reset for next cycle +// phy->previous_slot_offset_filtered = phy->slot_offset_filtered; +// phy->min_sync_cycle_count = 2; +// phy->slot_offset_filtered = 0; +// phy->slot_offset = 0; +// } +// else +// { +// phy->previous_t1 = ind.t1; +// phy->previous_t2 = ind.t2; +// } + } void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { @@ -2035,46 +2141,26 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_HARQ_INDICATION: - vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: + vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_CRC_INDICATION: - vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: + vnf_handle_nr_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RX_ULSCH_INDICATION: - vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: + vnf_handle_nr_uci_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RACH_INDICATION: - vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: + vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_SRS_INDICATION: - vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: + vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); break; - case NFAPI_RX_SR_INDICATION: - vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_RX_CQI_INDICATION: - vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_LBT_DL_INDICATION: - vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_NB_HARQ_INDICATION: - vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - - case NFAPI_NRACH_INDICATION: - vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7); - break; - case NFAPI_UE_RELEASE_RESPONSE: vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7); break; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index aba91d0d28..f66919434e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -430,18 +430,6 @@ struct timespec current_time; } send_mac_slot_indications(vnf_p7); - - - // // Call the scheduler - // struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - // pthread_mutex_lock(&gNB->UL_INFO_mutex); - // gNB->UL_INFO.frame = vnf_frame; - // gNB->UL_INFO.slot = vnf_slot; - - // gNB->UL_INFO.module_id = gNB->Mod_id; - // gNB->UL_INFO.CC_id = gNB->CC_id; - // gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - // pthread_mutex_unlock(&gNB->UL_INFO_mutex); } else if(selectRetval > 0) { diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index f901bfdded..625519b953 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -61,6 +61,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, debug_ch_est = fopen("debug_ch_est.txt","w"); #endif + //uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1]; + uint8_t nushift; int **ul_ch_estimates = gNB->pusch_vars[ul_id]->ul_ch_estimates; int **rxdataF = gNB->common_vars.rxdataF; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 3707669769..543002827d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -32,7 +32,6 @@ */ #include "nr_dlsch.h" -#include "../../../nfapi/oai_integration/vendor_ext.h" extern void set_taus_seed(unsigned int seed_type); @@ -264,21 +263,13 @@ int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { for (i=0; inumber_of_nr_dlsch_max; i++) { AssertFatal(gNB->dlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i); AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i); - //LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, - //gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); - LOG_D(PHY,"searching for harq_mask %x, rnti %x, gNB->dlsch[i][0]->rnti %x\n", gNB->dlsch[i][0]->harq_mask, rnti, gNB->dlsch[i][0]->rnti); + LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i, + gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index); if ((gNB->dlsch[i][0]->harq_mask >0) && (gNB->dlsch[i][0]->rnti==rnti)) return i; - else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) { - //printf("gNB->dlsch[i][0]->harq_mask = %d \n", gNB->dlsch[i][0]->harq_mask);; - first_free_index=i; - } - - } - if (type == SEARCH_EXIST) { - printf("type = %d \n", type); - return -1; + else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; } + if (type == SEARCH_EXIST) return -1; if (first_free_index != -1) gNB->dlsch[first_free_index][0]->rnti = 0; return first_free_index; @@ -293,10 +284,7 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB, uint8_t *sdu) { nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &pdsch_pdu->pdsch_pdu_rel15; - if (NFAPI_MODE == NFAPI_MODE_PNF) { - gNB->dlsch[0][0]->harq_mask = 1; - gNB->dlsch[0][0]->rnti = 4660; - } + int dlsch_id = find_nr_dlsch(rel15->rnti,gNB,SEARCH_EXIST); AssertFatal( (dlsch_id>=0) && (dlsch_idnumber_of_nr_dlsch_max), "illegal or no dlsch_id found!!! rnti %04x dlsch_id %d\n",rel15->rnti,dlsch_id); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 3fee7e5dff..13c7510833 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -430,22 +430,20 @@ void nr_processULSegment(void* arg) { p_procTime); if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) { -// #ifdef PRINT_CRC_CHECK - LOG_I(PHY, "Segment %d CRC OK\n",r); -// #endif +#ifdef PRINT_CRC_CHECK + LOG_D(PHY, "Segment %d CRC OK\n",r); +#endif rdata->decodeIterations = no_iteration_ldpc; } else { -// #ifdef PRINT_CRC_CHECK +#ifdef PRINT_CRC_CHECK LOG_I(PHY, "CRC NOK\n"); -// #endif +#endif rdata->decodeIterations = max_ldpc_iterations + 1; } for (int m=0; m < Kr>>3; m ++) { ulsch_harq->c[r][m]= (uint8_t) llrProcBuf[m]; - //printf("%x ", ulsch_harq->c[r][m]); } - //printf("\n"); //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); } @@ -512,7 +510,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, A = (harq_process->TBS)<<3; LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, n_layers %d\n",harq_pid,A,G, mcs, n_layers, nb_rb, Qm, n_layers); - //printf("ULSCH in %d.%d \n", frame, nr_tti_rx); if (R<1024) Coderate = (float) R /(float) 1024; diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 3b5fd2e04a..9159627286 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -166,15 +166,9 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu) { - printf("Inside nr_decode_pucch0. \n"); + int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - //Gokul - // printf("rxdataf buff: \n"); - // for(int i = 1;i<=5*7*14*512;++i){ - // if(gNB->RU_list[0]->common.rxdataF[0][i] != 0) - // printf("%d ",gNB->RU_list[0]->common.rxdataF[0][i]); - // } int nr_sequences; const uint8_t *mcs; @@ -1092,8 +1086,7 @@ void init_pucch2_luts() { void nr_decode_pucch2(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, - nfapi_nr_pucch_pdu_t* pucch_pdu) { - printf("Inside nr_decode_pucch2. \n"); + nfapi_nr_pucch_pdu_t* pucch_pdu) { int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 9bf00a6f4a..d5c0245fdc 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -577,7 +577,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_I(PHY,"Segment %u CRC OK\n\033[0m",r); + LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); if (r==0) { for (int i=0;i<10;i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t*)llrProcBuf)[i]); } @@ -587,7 +587,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, ret = no_iteration_ldpc; } else { - LOG_I(PHY,"CRC NOT OK\n\033[0m"); + LOG_D(PHY,"CRC NOT OK\n\033[0m"); ret = 1 + dlsch->max_ldpc_iterations; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c index 853a3f61cf..68a206e7c7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c @@ -38,31 +38,6 @@ //#define DEBUG_LLR_SIC -void PrintIntrinsics(char *s, char *dtype, void *x) { - if (strcmp(dtype,"int") == 0) { - int *tempb = (int *)x; - printf("%s: [%d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]); - } - if (strcmp(dtype,"short") == 0) { - short *tempb = (short *)x; - printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d]\n", s, tempb[0], tempb[1], tempb[2], tempb[3], - tempb[4], tempb[5], tempb[6], tempb[7]); - } - if (strcmp(dtype,"char") == 0) { - char *tempb = (char *)x; - printf("%s: [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]\n", s, - tempb[0], tempb[1], tempb[2], tempb[3], tempb[4], tempb[5], tempb[6], tempb[7], - tempb[8], tempb[9],tempb[10],tempb[11],tempb[12],tempb[13],tempb[14],tempb[15]); - } - if (strcmp(dtype,"float") == 0) { - float *tempb = (float *)x; - printf("%s: [%f, %f, %f, %f]\n", s, tempb[0], tempb[1], tempb[2], tempb[3]); - } - if (strcmp(dtype,"double") == 0) { - double *tempb = (double *)x; - printf("%s: [%f, %f]\n", s, tempb[0], tempb[1]); - } -} int16_t nr_zeros[8] __attribute__ ((aligned(16))) = {0,0,0,0,0,0,0,0}; int16_t nr_ones[8] __attribute__ ((aligned(16))) = {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; @@ -759,45 +734,20 @@ void nr_dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms, for (i=0; i| add CRC |---->b ///////////////////////// /////////// - - // int i; - // printf("ulsch (tx): \n"); - // for (i=0;i<(A>>3);i++) - // printf("%x ",harq_process->a[i]); - // printf("\n"); - + /* + int i; + printf("ulsch (tx): \n"); + for (i=0;i<(A>>3);i++) + printf("%02x.",a[i]); + printf("\n"); + */ if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 3b9573bcbc..012e088dff 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -111,6 +111,8 @@ void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, nr_fill_dci(gNB,frame,slot,pdcch_pdu); + + } void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, @@ -138,7 +140,6 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ - //if(NFAPI_MODE == NFAPI_MODE_VNF) PHY_VARS_gNB *gNB; // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; @@ -185,30 +186,26 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - if(NFAPI_MODE != NFAPI_MODE_VNF){ - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nfapi_nr_pdcch_pdu(gNB, frame, slot, &dl_tti_pdu->pdcch_pdu); - } + pdcch_received = 1; break; case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { - LOG_I(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - if(NFAPI_MODE != NFAPI_MODE_VNF){ - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); - } } } } @@ -255,7 +252,6 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ { Sched_INFO->DL_req->SFN = frame; Sched_INFO->DL_req->Slot = slot; - //printf("DL tti Frame = %d, slot = %d. \n",frame,slot); oai_nfapi_dl_tti_req(Sched_INFO->DL_req); } if (Sched_INFO->TX_req->Number_of_PDUs > 0) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 2d3aec5137..4a99b311db 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -623,7 +623,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { (ulsch_harq->slot == slot_rx) && (ulsch_harq->handled == 0)){ - LOG_I(PHY, "PUSCH detection started in frame %d slot %d\n", + LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n", frame_rx,slot_rx); #ifdef DEBUG_RXDATA @@ -683,10 +683,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); } - if (pucch_decode_done || pusch_decode_done) { - T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); return 0; } diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 56efbdbad4..3417bf7653 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -123,7 +123,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); - dlsch0_harq->status = ACTIVE; //Gokul + dlsch0_harq->status = ACTIVE; if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 0dcc057867..85f6d90bbe 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -472,7 +472,7 @@ harq_result_t downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int dl_harq->round = 0; dl_harq->status = ACTIVE; dl_harq->DCINdi = ndi; - //dl_harq->first_tx = 0; + dl_harq->first_tx = 0; result_harq = NEW_TRANSMISSION_HARQ; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 21bc041f52..730e78c162 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -121,21 +121,6 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, return 0; } -void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index) -{ - return; -} - -int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, - const int CC_id, - const uint8_t gNB_id, - const frame_t frameP, - const rb_id_t Srb_id, - uint8_t *buffer_pP) -{ - return 0; -} - void rrc_data_ind( const protocol_ctxt_t *const ctxt_pP, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 94f3931424..eacf4f54a9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -324,12 +324,12 @@ bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_t slot){ - gNB_MAC_INST *mac = RC.nrmac[module_idP]; - nfapi_nr_config_request_scf_t *cfg = &mac->config[0]; + protocol_ctxt_t ctxt; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); const int bwp_id = 1; + gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -374,6 +374,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, const int last_slot = (slot + num_slots - 1) % num_slots; uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); + clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 02e0e42139..b428805882 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -851,15 +851,7 @@ void nr_schedule_ue_spec(module_id_t module_id, const int bwpid = sched_ctrl->active_bwp->bwp_Id; const int coresetid = sched_ctrl->coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; - //nfapi_nr_dl_tti_pdcch_pdu_rel15_t temp; - // if(NFAPI_MODE == NFAPI_MODE_VNF){ - // memcpy(temp,gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid],sizeof(nfapi_nr_dl_tti_pdcch_pdu_rel15_t)); - // pdcch_pdu = temp; - - // } - if (!pdcch_pdu) { - printf("creating pdcch pdu, pdcch_pdu = NULL. \n"); nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; @@ -902,14 +894,6 @@ void nr_schedule_ue_spec(module_id_t module_id, pdsch_pdu->mcsTable[0] = ps->mcsTableIdx; AssertFatal(harq->round<4,"%d",harq->round); pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round]; - // if (NFAPI_MODE == NFAPI_MODE_VNF){ // done since uplink isnt operational yet which means harq structures dont get filled properly - // pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq_rounds]; - // if (harq_rounds % 5 == 0 && harq_rounds!=0){ - // harq_rounds = 0; - // harq_pid = (harq_pid + 1) % 16; - // } - // harq_rounds++; - // } pdsch_pdu->TBSize[0] = TBS; pdsch_pdu->dataScramblingId = *scc->physCellId; @@ -1018,10 +1002,6 @@ void nr_schedule_ue_spec(module_id_t module_id, const int dci_format = f ? NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0; const int rnti_type = NR_RNTI_C; - // if (NFAPI_MODE == NFAPI_MODE_VNF){ - // dci_payload.harq_pid = harq_pid; - // dci_payload.tpc = 2; - // } fill_dci_pdu_rel15(scc, UE_info->secondaryCellGroup[UE_id], dci_pdu, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 9a50297dd1..b3d2ecb0b2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -62,7 +62,6 @@ #include "common/ran_context.h" extern RAN_CONTEXT_t RC; -uint8_t count = 0; uint8_t harq_pid_ul = -1; int flag = 0; // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs /// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config) @@ -1365,11 +1364,6 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, case NR_UL_DCI_FORMAT_0_1: switch (rnti_type) { case NR_RNTI_C: - harq_pid_ul = (harq_pid_ul + 1) % 16; - if (harq_pid_ul == 0) - flag = !flag; - dci_pdu_rel15->ndi = flag; - // Indicating a DL DCI format 1bit pos = 1; *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos); @@ -1402,7 +1396,6 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); // HARQ process number 4bit pos += 4; - dci_pdu_rel15->harq_pid = harq_pid_ul; *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); // 1st Downlink assignment index pos += dci_pdu_rel15->dai[0].nbits; @@ -1816,7 +1809,6 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secon const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig->pdsch_ServingCellConfig->choice.setup; const int nrofHARQ = pdsch->nrofHARQ_ProcessesForPDSCH ? get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8; - printf("nrofHARQ = %d\n", nrofHARQ); // add all available DL HARQ processes for this UE create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ); for (int harq = 0; harq < nrofHARQ; harq++) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 6f5946fe27..b667c8d977 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -45,6 +45,11 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot]; + if (NFAPI_MODE == NFAPI_MODE_VNF){ + future_ul_tti_req->SFN = pucch->frame; + future_ul_tti_req->Slot = pucch->ul_slot; + } + AssertFatal(future_ul_tti_req->SFN == pucch->frame && future_ul_tti_req->Slot == pucch->ul_slot, "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n", @@ -507,9 +512,10 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) - NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[2]; - if(NFAPI_MODE == NFAPI_MODE_VNF) - curr_pucch->csi_bits = 0; + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; + if(NFAPI_MODE == NFAPI_MODE_VNF){ + curr_pucch->csi_bits = 0; curr_pucch->sr_flag = 0; curr_pucch->dai_c = 0; + } AssertFatal(curr_pucch->csi_bits == 0 && !curr_pucch->sr_flag && curr_pucch->dai_c == 0, @@ -1000,63 +1006,51 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) -{ NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; - UE_info->active[0] = 1; - UE_info->rnti[0] = uci_01->rnti; +{ int UE_id = find_nr_UE_id(mod_id, uci_01->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); return; } - //NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - // tpc (power control) - sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, - uci_01->ul_cqi, - 30); + if (((uci_01->pduBitmap >> 1) & 0x01)) { + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { + const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; + const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; + NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); + if (!harq) + break; + DevAssert(harq->is_waiting); + const int8_t pid = sched_ctrl->feedback_dl_harq.head; + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); + } + } - // NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; - // const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - const int num_slots = 20; - - // if (((uci_01->pduBitmap >> 1) & 0x01)) { - // // iterate over received harq bits - // for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { - // const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; - // const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; - // const int feedback_slot = (slot - 1 + num_slots) % num_slots; - // /* In case of realtime problems: we can only identify a HARQ process by - // * timing. If the HARQ process's feedback_slot is not the one we - // * expected, we assume that processing has been aborted and we need to - // * skip this HARQ process, which is what happens in the loop below. If - // * you don't experience real-time problems, you might simply revert the - // * commit that introduced these changes. */ - // int8_t pid = sched_ctrl->feedback_dl_harq.head; - // DevAssert(pid >= 0); - // while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { - // LOG_W(MAC, - // "expected feedback slot %d, but found %d instead\n", - // sched_ctrl->harq_processes[pid].feedback_slot, - // feedback_slot); - // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - // handle_dl_harq(mod_id, UE_id, pid, 0); - // pid = sched_ctrl->feedback_dl_harq.head; - // DevAssert(pid >= 0); - // } - // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - // NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; - // DevAssert(harq->is_waiting); - // handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); - // } - // } + // check scheduling request result, confidence_level == 0 is good + if (uci_01->pduBitmap & 0x1 && uci_01->sr->sr_indication && uci_01->sr->sr_confidence_level == 0 && uci_01->ul_cqi >= 148) { + // SR detected with SNR >= 10dB + sched_ctrl->SR |= true; + LOG_D(MAC, "SR UE %04x ul_cqi %d\n", uci_01->rnti, uci_01->ul_cqi); + } + + // tpc (power control) only if we received AckNack or positive SR. For a + // negative SR, the UE won't have sent anything, and the SNR is not valid + if (((uci_01->pduBitmap >> 1) & 0x1) || sched_ctrl->SR) { + sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_01->ul_cqi, 30); + sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640; + } } void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) -{ int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); +{ + int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); if (UE_id < 0) { LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); return; @@ -1064,57 +1058,25 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, NR_CSI_MeasConfig_t *csi_MeasConfig = RC.nrmac[mod_id]->UE_info.secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - if (NFAPI_MODE == NFAPI_MODE_PNF){ - UE_info->active[0] = 1; - UE_info->rnti[0] = uci_234->rnti; - } - + // tpc (power control) sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_234->ul_cqi, 30); sched_ctrl->pucch_snrx10 = uci_234->ul_cqi * 5 - 640; - // NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; - // const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - const int num_slots = 20; - // if ((uci_234->pduBitmap >> 1) & 0x01) { - // // iterate over received harq bits - // for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { - // const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; - // const int feedback_slot = (slot - 1 + num_slots) % num_slots; - // /* In case of realtime problems: we can only identify a HARQ process by - // * timing. If the HARQ process's feedback_slot is not the one we - // * expected, we assume that processing has been aborted and we need to - // * skip this HARQ process, which is what happens in the loop below. If - // * you don't experience real-time problems, you might simply revert the - // * commit that introduced these changes. */ - // int8_t pid = sched_ctrl->feedback_dl_harq.head; - // DevAssert(pid >= 0); - // while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { - // LOG_W(MAC, - // "expected feedback slot %d, but found %d instead\n", - // sched_ctrl->harq_processes[pid].feedback_slot, - // feedback_slot); - // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - // handle_dl_harq(mod_id, UE_id, pid, 0); - // pid = sched_ctrl->feedback_dl_harq.head; - // DevAssert(pid >= 0); - // } - // remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - // NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; - // DevAssert(harq->is_waiting); - // handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); - // } - // } - if ((uci_234->pduBitmap >> 2) & 0x01) { - //API to parse the csi report and store it into sched_ctrl - extract_pucch_csi_report (csi_MeasConfig, uci_234, frame, slot, UE_id, mod_id); - //TCI handling function - tci_handling(mod_id, UE_id,frame, slot); - } - if ((uci_234->pduBitmap >> 3) & 0x01) { - //@TODO:Handle CSI Report 2 + if ((uci_234->pduBitmap >> 1) & 0x01) { + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { + const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; + NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); + if (!harq) + break; + DevAssert(harq->is_waiting); + const int8_t pid = sched_ctrl->feedback_dl_harq.head; + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); + } } if ((uci_234->pduBitmap >> 2) & 0x01) { //API to parse the csi report and store it into sched_ctrl @@ -1127,7 +1089,6 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, } } - // function to update pucch scheduling parameters in UE list when a USS DL is scheduled // this function returns an index to NR_sched_pucch structure // currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1 @@ -1197,7 +1158,6 @@ int nr_acknack_scheduling(int mod_id, nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); memset(csi_pucch, 0, sizeof(*csi_pucch)); pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f; - printf("pucch frame filled. \n"); pucch->ul_slot = (s + 2) % n_slots_frame; } } @@ -1205,6 +1165,7 @@ int nr_acknack_scheduling(int mod_id, /* if the UE's next PUCCH occasion is after the possible UL slots (within the * same frame) or wrapped around to the next frame, then we assume there is * no possible PUCCH allocation anymore */ + if(NFAPI_MODE == NFAPI_MONOLITHIC) if ((pucch->frame == frame && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)) || (pucch->frame == frame + 1)) @@ -1216,6 +1177,8 @@ int nr_acknack_scheduling(int mod_id, get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); /* there is a HARQ. Check whether we can use it for this ACKNACK */ + if(NFAPI_MODE == NFAPI_MODE_VNF) + return 0; if (pucch->dai_c > 0) { /* this UE already has a PUCCH occasion */ DevAssert(pucch->frame == frame); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 2190886226..1481865128 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -105,10 +105,6 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) } UL_info->uci_ind.num_ucis = 0; - // if(NFAPI_MODE != NFAPI_MODE_PNF) - // // mark corresponding PUCCH resources as free - // // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs - // RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; } @@ -139,18 +135,18 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - //Gokul - // nr_rx_sdu(UL_info->module_id, - // UL_info->CC_id, - // UL_info->rx_ind.sfn, - // UL_info->rx_ind.slot, - // rx->rnti, - // crc->tb_crc_status ? NULL : rx->pdu, - // rx->pdu_length, - // rx->timing_advance, - // rx->ul_cqi, - // rx->rssi); - //handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); + + nr_rx_sdu(UL_info->module_id, + UL_info->CC_id, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + rx->rnti, + crc->tb_crc_status ? NULL : rx->pdu, + rx->pdu_length, + rx->timing_advance, + rx->ul_cqi, + rx->rssi); + handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) } // for (i=0;irx_ind.number_of_pdus;i++) @@ -173,7 +169,6 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) } void NR_UL_indication(NR_UL_IND_t *UL_info) { - //printf("Inside NR UL Indication. \n"); AssertFatal(UL_info!=NULL,"UL_INFO is null\n"); #ifdef DUMP_FAPI dump_ul(UL_info); @@ -183,7 +178,6 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { NR_Sched_Rsp_t *sched_info = &NR_Sched_INFO[module_id][CC_id]; NR_IF_Module_t *ifi = nr_if_inst[module_id]; gNB_MAC_INST *mac = RC.nrmac[module_id]; - nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rach_pdus:%d rx_ind:%d crcs:%d]\n", UL_info->frame,UL_info->slot, module_id,CC_id, UL_info->rach_ind.number_of_pdus, @@ -216,7 +210,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { (UL_info->frame+((UL_info->slot>(9-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%10); */ - + nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; int spf = get_spf(cfg); gNB_dlsch_ulsch_scheduler(module_id, (UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024, @@ -245,7 +239,10 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ifi->NR_Schedule_response(sched_info); } - + LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n", + sched_info->frame, + sched_info->slot, + sched_info->DL_req->dl_tti_request_body.nPDUs); } } } diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 1de76bb257..83a6207eec 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -1144,7 +1144,7 @@ extern "C" { case 46080000: //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 65; + openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].tx_bw = 40e6; openair0_cfg[0].rx_bw = 40e6; break; @@ -1159,7 +1159,7 @@ extern "C" { case 15360000: //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 40; + openair0_cfg[0].tx_sample_advance = 45; openair0_cfg[0].tx_bw = 10e6; openair0_cfg[0].rx_bw = 10e6; break; From 8889d6d8089c415f9fd3dabb757704ef1de92e66 Mon Sep 17 00:00:00 2001 From: Gokul Srinivasan Date: Sun, 30 May 2021 21:05:12 +0000 Subject: [PATCH 095/185] Add .gitlab-ci.yml --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1 @@ + From 4dc9d22f166c73f0f678033f1d6326ee6847b6d9 Mon Sep 17 00:00:00 2001 From: Gokul Srinivasan Date: Mon, 7 Jun 2021 22:41:08 +0000 Subject: [PATCH 096/185] bugfix in gNB_scheduler_uci.c --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index b667c8d977..46ccc8ac53 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1128,8 +1128,10 @@ int nr_acknack_scheduling(int mod_id, __func__, pucch->csi_bits); /* if the currently allocated PUCCH of this UE is full, allocate it */ - if (NFAPI_MODE == NFAPI_MODE_VNF) - pucch->sr_flag = 1; pucch->dai_c = 1; + if (NFAPI_MODE == NFAPI_MODE_VNF){ + pucch->sr_flag = 1; + pucch->dai_c = 1; + } if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in From e93df00434d6e7f6d155c78281dcc249a16fe97b Mon Sep 17 00:00:00 2001 From: Gokul Srinivasan Date: Tue, 8 Jun 2021 12:46:34 +0000 Subject: [PATCH 097/185] Update nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h, openair1/SCHED_NR_UE/fapi_nr_ue_l1.c, nfapi/oai_integration/nfapi_pnf.h, nfapi/oai_integration/nfapi_pnf.c files --- nfapi/oai_integration/nfapi_pnf.c | 1 - nfapi/oai_integration/nfapi_pnf.h | 1 + nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h | 8 +------- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 1 - 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 98757b09d0..ed0bafa300 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -73,7 +73,6 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; extern int sync_var; -char uecap_xer_in; extern void init_eNB_afterRU(void); extern void init_UE_stub(int nb_inst,int,int); diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index b3ab7cbdbc..61d4847eba 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -21,6 +21,7 @@ #if !defined(NFAPI_PNF_H__) #define NFAPI_PNF_H__ +extern nfapi_ue_release_request_body_t release_rntis; int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 9df9be4cbd..0436f92a8d 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -972,7 +972,7 @@ typedef struct typedef struct { - uint32_t ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) + int ss_pbch_power;//SSB Block Power Value: TBD (-60..50 dBm) uint8_t bch_payload;//Defines option selected for generation of BCH payload, see Table 3-13 (v0.0.011 Value: 0: MAC generates the full PBCH payload 1: PHY generates the timing PBCH bits 2: PHY generates the full PBCH payload uint8_t scs_common;//subcarrierSpacing for common, used for initial access and broadcast message. [38.211 sec 4.2] Value:0->3 @@ -1058,12 +1058,6 @@ typedef struct { fapi_nr_tdd_table_t tdd_table; fapi_nr_prach_config_t prach_config; - fapi_nr_dl_bwp_common_config_t dl_bwp_common; - fapi_nr_dl_bwp_dedicated_config_t dl_bwp_dedicated; - - fapi_nr_ul_bwp_common_config_t ul_bwp_common; - fapi_nr_ul_bwp_dedicated_config_t ul_bwp_dedicated; - } fapi_nr_config_request_t; #endif diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 3417bf7653..c8ac871bbf 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -123,7 +123,6 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); - dlsch0_harq->status = ACTIVE; if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. From 6210519d519caffd5915e38bd42c51e07b2d90a9 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 15 Jun 2021 18:35:46 +0530 Subject: [PATCH 098/185] Bugfix - UL info filling --- nfapi/oai_integration/nfapi_vnf.c | 99 ++- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 198 +++--- .../vnf/public_inc/nfapi_vnf_interface.h | 10 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 655 +++++++++--------- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 2 +- 5 files changed, 560 insertions(+), 404 deletions(-) diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 12dda62eaf..8f30a091ab 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -596,7 +596,7 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { - printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); + //printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); if (sync==1 && nfapi_sync_var!=0) { @@ -1014,6 +1014,98 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ return 1; } +//NR phy indication + +int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + ind->number_crcs = 1; + if (ind->number_crcs > 0) + gNB->UL_INFO.crc_ind.crc_list = malloc(sizeof(nfapi_nr_crc_t)*ind->number_crcs); + + for (int i=0; inumber_crcs; i++) + memcpy(&gNB->UL_INFO.crc_ind.crc_list[i], &ind->crc_list[i], sizeof(ind->crc_list[0])); + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.rx_ind.pdu_list = malloc(sizeof(nfapi_nr_rx_data_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) + memcpy(&gNB->UL_INFO.rx_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + if (ind->num_ucis > 0) + gNB->UL_INFO.uci_ind.uci_list = malloc(sizeof(nfapi_nr_uci_t)*ind->num_ucis); + + for (int i=0; inum_ucis; i++) + memcpy(&gNB->UL_INFO.uci_ind.uci_list[i], &ind->uci_list[i], sizeof(ind->uci_list[0])); + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.srs_ind.pdu_list = malloc(sizeof(nfapi_nr_srs_indication_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) { + memcpy(&gNB->UL_INFO.srs_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + LOG_D(MAC, "%s() NFAPI SFN/Slot:%d.%d SRS_IND:number_of_pdus:%d UL_INFO:pdus:%d\n", + __FUNCTION__, + ind->sfn,ind->slot, ind->number_of_pdus, gNB->UL_INFO.srs_ind.number_of_pdus + ); + } + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + + if (ind->number_of_pdus > 0) + gNB->UL_INFO.rach_ind.pdu_list = malloc(sizeof(nfapi_nr_prach_indication_pdu_t)*ind->number_of_pdus); + + for (int i=0; inumber_of_pdus; i++) { + memcpy(&gNB->UL_INFO.rach_ind.pdu_list[i], &ind->pdu_list[i], sizeof(ind->pdu_list[0])); + + LOG_D(MAC, "%s() NFAPI SFN/Slot:%d.%d RACH_IND:number_of_pdus:%d UL_INFO:pdus:%d\n", + __FUNCTION__, + ind->sfn,ind->slot, ind->number_of_pdus, gNB->UL_INFO.rach_ind.number_of_pdus + ); + } + + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + + return 1; +} + +//end NR phy indication + int phy_lbt_dl_indication(struct nfapi_vnf_p7_config *config, nfapi_lbt_dl_indication_t *ind) { // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data); //mac_lbt_dl_ind(p7_vnf->mac, ind); @@ -1179,6 +1271,11 @@ void *vnf_nr_p7_thread_start(void *ptr) { p7_vnf->config->lbt_dl_indication = &phy_lbt_dl_indication; p7_vnf->config->nb_harq_indication = &phy_nb_harq_indication; p7_vnf->config->nrach_indication = &phy_nrach_indication; + p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication; + p7_vnf->config->nr_rx_data_indication = &phy_nr_rx_data_indication; + p7_vnf->config->nr_uci_indication = &phy_nr_uci_indication; + p7_vnf->config->nr_rach_indication = &phy_nr_rach_indication; + p7_vnf->config->nr_srs_indication = &phy_nr_srs_indication; p7_vnf->config->malloc = &vnf_allocate; p7_vnf->config->free = &vnf_deallocate; p7_vnf->config->trace = &vnf_trace; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 4097217f99..3a90ca4363 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -361,7 +361,7 @@ static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - printf("Packing ssb. \n"); + //printf("Packing ssb. \n"); nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; return( @@ -3625,7 +3625,7 @@ static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; - pack_nr_uci_pucch_0_1(uci_pdu, ppWritePackedMsg, end); + pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { @@ -3650,7 +3650,7 @@ static uint8_t pack_nr_uci_indication(void *msg, uint8_t **ppWritePackedMsg, uin for(int i=0; inum_ucis;i++) { - if(!pack_nr_uci_indication_body(&(pNfapiMsg->uci_list[i]),ppWritePackedMsg,end)) + if(!pack_nr_uci_indication_body(pNfapiMsg->uci_list,ppWritePackedMsg,end)) return 0; } @@ -3700,7 +3700,7 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - printf("result of pack dl_tti_req is %d. \n",result); + //printf("result of pack dl_tti_req is %d. \n",result); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: @@ -6370,15 +6370,8 @@ static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPack } -static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) { - // uint8_t *ptr = *ppReadPackedMsg; - // printf("\n Read P7 message rx data indication unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; printf("\n"); @@ -6390,7 +6383,7 @@ static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t * for(int i=0; inumber_of_pdus;i++) { - if(!unpack_nr_rx_data_indication_body(&pNfapiMsg->pdu_list, ppReadPackedMsg, end)) + if(!unpack_nr_rx_data_indication_body(pNfapiMsg->pdu_list, ppReadPackedMsg, end)) return 0; } @@ -6399,10 +6392,8 @@ return 1; //NR CRC INDICATION -static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +static uint8_t unpack_nr_crc_indication_body(nfapi_nr_crc_t* value, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_crc_t* value = (nfapi_nr_crc_t*)tlv; - if(!(pull32(ppReadPackedMsg, &value->handle, end) && pull16(ppReadPackedMsg, &value->rnti, end) && pull8(ppReadPackedMsg, &value->harq_id, end) && @@ -6415,32 +6406,31 @@ static uint8_t unpack_nr_crc_indication_body(void* tlv, uint8_t **ppReadPackedMs )) return 0; + //memcpy((nfapi_nr_crc_t *)tlv,value,sizeof(nfapi_nr_crc_t)); + return 1; } -static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_crc_indication_t *msg, nfapi_p7_codec_config_t* config) { - uint8_t *ptr = *ppReadPackedMsg; - // printf("\n Read P7 message indication unpack: "); - // while(ptr < end){ - // printf(" %d ", *ptr); - // ptr++; - // } - // printf("\n"); - nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t*)msg; - - if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && - pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && + nfapi_nr_crc_indication_t *pNfapiMsg = (nfapi_nr_crc_indication_t *) msg; + // pNfapiMsg = (nfapi_nr_crc_indication_t *) malloc(sizeof(nfapi_nr_crc_indication_t)); + // pNfapiMsg->crc_list = (nfapi_nr_crc_t *) malloc(sizeof(nfapi_nr_crc_t)); + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot, end) && pull16(ppReadPackedMsg, &pNfapiMsg->number_crcs, end) )) - return 0; + return 0; for(int i=0; inumber_crcs;i++) { - if(!unpack_nr_crc_indication_body(&pNfapiMsg->crc_list,ppReadPackedMsg,end)) + if(!unpack_nr_crc_indication_body(pNfapiMsg->crc_list,ppReadPackedMsg,end)) + //if(!unpack_nr_crc_indication_body(value,ppReadPackedMsg,end)) return 0; } + printf("Done \n"); return 1; } @@ -6489,7 +6479,7 @@ return 1; //NR RACH -static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +static uint8_t unpack_nr_rach_indication_body(nfapi_nr_prach_indication_pdu_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_prach_indication_pdu_t* value = (nfapi_nr_prach_indication_pdu_t*)tlv; @@ -6502,6 +6492,7 @@ static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedM pull8(ppReadPackedMsg, &value->num_preamble, end) )) return 0; + value->preamble_list = (nfapi_nr_prach_indication_preamble_t*) malloc(sizeof(nfapi_nr_prach_indication_preamble_t) * value->num_preamble); for(int i = 0; i < value->num_preamble; i++) { if(!(pull8(ppReadPackedMsg, &value->preamble_list->preamble_index, end) && @@ -6513,7 +6504,7 @@ static uint8_t unpack_nr_rach_indication_body(void* tlv, uint8_t **ppReadPackedM return 1; } -static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { +static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rach_indication_t* msg, nfapi_p7_codec_config_t* config) { nfapi_nr_rach_indication_t *pNfapiMsg = (nfapi_nr_rach_indication_t*)msg; if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && @@ -6521,10 +6512,10 @@ static uint8_t unpack_nr_rach_indication(uint8_t **ppReadPackedMsg, uint8_t *end pull8(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) )) return 0; - + pNfapiMsg->pdu_list = (nfapi_nr_prach_indication_pdu_t*) malloc(sizeof(nfapi_nr_prach_indication_pdu_t) * pNfapiMsg->number_of_pdus); for(int i=0; i< pNfapiMsg->number_of_pdus;i++) { - if(!unpack_nr_rach_indication_body(&pNfapiMsg->pdu_list,ppReadPackedMsg,end)) + if(!unpack_nr_rach_indication_body(pNfapiMsg->pdu_list,ppReadPackedMsg,end)) return 0; } @@ -6533,16 +6524,16 @@ return 1; //NR UCI -static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; uint8_t *ptr = *ppReadPackedMsg; - printf("\n Read P7 message uci_0_1 indication unpack: "); - while(ptr < end){ - printf(" %d ", *ptr); - ptr++; - } - printf("\n"); + // printf("\n Read P7 message uci_0_1 indication unpack: "); + // while(ptr < end){ + // printf(" %d ", *ptr); + // ptr++; + // } + // printf("\n"); if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && pull32(ppReadPackedMsg, &value->handle, end) && @@ -6554,34 +6545,33 @@ static uint8_t unpack_nr_uci_pucch_0_1(void* tlv, uint8_t **ppReadPackedMsg, uin )) return 0; if (value->pduBitmap & 0x01) { //SR + value->sr = (nfapi_nr_sr_pdu_0_1_t*) malloc(sizeof(nfapi_nr_sr_pdu_0_1_t)); if(!(pull8(ppReadPackedMsg, &value->sr->sr_indication, end) && pull8(ppReadPackedMsg, &value->sr->sr_confidence_level, end) )) return 0; } - // if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - // uint8_t* temp; //&value->harq->num_harq &value->harq->harq_confidence_level &value->harq->harq_list[0].harq_value - // temp = (uint8_t*) malloc(sizeof(uint8_t)); - // //printf("value->harq->num_harq = %d \n", value->harq->num_harq); - // // if(!(pull8(ppReadPackedMsg, temp, end) && - // // pull8(ppReadPackedMsg, temp, end) - // // )) - // // return 0; - - // // for(int i=0; i<1;i++) - // // { - // // if(!(pull8(ppReadPackedMsg, temp, end) - // // )) - // // return 0; - // // } - // } + if (((value->pduBitmap >> 1) & 0x01)) { //HARQ + value->harq = (nfapi_nr_harq_pdu_0_1_t*) malloc(sizeof(nfapi_nr_harq_pdu_0_1_t)); + if(!(pull8(ppReadPackedMsg, &value->harq->num_harq, end) && + pull8(ppReadPackedMsg, &value->harq->harq_confidence_level, end) + )) + return 0; + value->harq->harq_list = (nfapi_nr_harq_t*) malloc(sizeof(nfapi_nr_harq_t*) * value->harq->num_harq); + for(int i=0; iharq->num_harq;i++) + { + if(!(pull8(ppReadPackedMsg, &value->harq->harq_list->harq_value, end) + )) + return 0; + } + } return 1; } -static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { +static uint8_t unpack_nr_uci_pucch_2_3_4(nfapi_nr_uci_pucch_pdu_format_2_3_4_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_uci_pucch_pdu_format_2_3_4_t* value = (nfapi_nr_uci_pucch_pdu_format_2_3_4_t*) tlv; if(!(pull8(ppReadPackedMsg, &value->pduBitmap, end) && @@ -6594,43 +6584,53 @@ static uint8_t unpack_nr_uci_pucch_2_3_4(void* tlv, uint8_t **ppReadPackedMsg, u )) return 0; if (value->pduBitmap & 0x01) { //SR - if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end) && - pullarray8(ppReadPackedMsg, value->sr.sr_payload, (int)(value->sr.sr_bit_len / 8) + 1, (int)(value->sr.sr_bit_len / 8) + 1, end) - )) - return 0; + if(!(pull16(ppReadPackedMsg, &value->sr.sr_bit_len, end))) + return 0; + + value->sr.sr_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->sr.sr_bit_len/8))); + + if(!(pullarray8(ppReadPackedMsg, &value->sr.sr_payload[0], (int)(value->sr.sr_bit_len / 8), (int)(value->sr.sr_bit_len / 8), end))) + return 0; } if (((value->pduBitmap >> 1) & 0x01)) { //HARQ - if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end) && - pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end) && - pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8) + 1, (int)(value->harq.harq_bit_len / 8) + 1, end) - )) + if(!(pull8(ppReadPackedMsg, &value->harq.harq_crc, end)) && + (pull16(ppReadPackedMsg, &value->harq.harq_bit_len, end))) + return 0; + + value->harq.harq_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->harq.harq_bit_len/8 ))); + + if(!(pullarray8(ppReadPackedMsg, value->harq.harq_payload, (int)(value->harq.harq_bit_len / 8), (int)(value->harq.harq_bit_len / 8), end))) return 0; } if (((value->pduBitmap >> 2) & 0x01)) { //CSI-1 - if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end) && - pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end) && - pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, (int)(value->csi_part1.csi_part1_bit_len / 8) + 1, end) - )) - return 0; + if(!(pull8(ppReadPackedMsg, &value->csi_part1.csi_part1_crc, end)) && + (pull16(ppReadPackedMsg, &value->csi_part1.csi_part1_bit_len, end))) + return 0; + + value->csi_part1.csi_part1_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->csi_part1.csi_part1_bit_len/8))); + +// if(!(pullarray8(ppReadPackedMsg, value->csi_part1.csi_part1_payload, (int)(value->csi_part1.csi_part1_bit_len / 8), (int)(value->csi_part1.csi_part1_bit_len / 8), end))) +// return 0; } if (((value->pduBitmap >> 3) & 0x01)) { //CSI-2 - if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end) && - pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end) && - pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, (int)(value->csi_part2.csi_part2_bit_len / 8) + 1, end) - )) + if(!(pull8(ppReadPackedMsg, &value->csi_part2.csi_part2_crc, end)) && + (pull16(ppReadPackedMsg, &value->csi_part2.csi_part2_bit_len, end))) + return 0; + + value->csi_part2.csi_part2_payload = (uint8_t*) malloc(sizeof(uint8_t) * ((value->csi_part2.csi_part2_bit_len/8 ))); + + if(!(pullarray8(ppReadPackedMsg, value->csi_part2.csi_part2_payload, (int)(value->csi_part2.csi_part2_bit_len / 8) , (int)(value->csi_part2.csi_part2_bit_len / 8) , end))) return 0; } return 1; } -static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +static uint8_t unpack_nr_uci_indication_body(nfapi_nr_uci_t* value, uint8_t **ppReadPackedMsg, uint8_t *end) { - nfapi_nr_uci_t* value = (nfapi_nr_uci_t*)tlv; - if(!(pull16(ppReadPackedMsg, &value->pdu_type, end) && pull16(ppReadPackedMsg, &value->pdu_size, end) )) @@ -6643,12 +6643,12 @@ static uint8_t unpack_nr_uci_indication_body(void* tlv, uint8_t **ppReadPackedMs case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu = &value->pucch_pdu_format_0_1; - unpack_nr_uci_pucch_0_1(&uci_pdu, ppReadPackedMsg, end); + unpack_nr_uci_pucch_0_1(uci_pdu, ppReadPackedMsg, end); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - unpack_nr_uci_pucch_2_3_4(&uci_pdu, ppReadPackedMsg, end); + unpack_nr_uci_pucch_2_3_4(uci_pdu, ppReadPackedMsg, end); break; } } @@ -6668,7 +6668,7 @@ static uint8_t unpack_nr_uci_indication(uint8_t **ppReadPackedMsg, uint8_t *end, for(int i=0; inum_ucis;i++) { - if(!unpack_nr_uci_indication_body(&pNfapiMsg->uci_list,ppReadPackedMsg,end)) + if(!unpack_nr_uci_indication_body(pNfapiMsg->uci_list,ppReadPackedMsg,end)) return 0; } @@ -8711,36 +8711,52 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * break; case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)) - result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)){ + nfapi_nr_rx_data_indication_t* msg = (nfapi_nr_rx_data_indication_t*) pMessageHeader; + msg->pdu_list = (nfapi_nr_rx_data_pdu_t*) malloc(sizeof(nfapi_nr_rx_data_pdu_t)); + msg->pdu_list->pdu = (uint8_t *) malloc(sizeof(uint8_t)); + result = unpack_nr_rx_data_indication(&pReadPackedMessage, end, msg, config); + } else return -1; break; case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)) - result = unpack_nr_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION, unpackedBufLen)){ + + nfapi_nr_crc_indication_t* msg = (nfapi_nr_crc_indication_t*) pMessageHeader; + msg->crc_list = (nfapi_nr_crc_t*) malloc(sizeof(nfapi_nr_crc_t)); + result = unpack_nr_crc_indication(&pReadPackedMessage,end , msg, config); + } else return -1; break; case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)) - result = unpack_nr_uci_indication(&pReadPackedMessage, end, pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION, unpackedBufLen)){ + nfapi_nr_uci_indication_t* msg = (nfapi_nr_uci_indication_t*) pMessageHeader; + msg->uci_list = (nfapi_nr_uci_t*) malloc(sizeof(nfapi_nr_uci_t)); + result = unpack_nr_uci_indication(&pReadPackedMessage, end, msg, config); + } else return -1; break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)) - result = unpack_nr_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION, unpackedBufLen)){ + nfapi_nr_srs_indication_t* msg = (nfapi_nr_srs_indication_t*) pMessageHeader; + msg->pdu_list = (nfapi_nr_srs_indication_pdu_t*) malloc(sizeof(nfapi_nr_srs_indication_pdu_t)); + result = unpack_nr_srs_indication(&pReadPackedMessage, end, msg, config); + } else return -1; break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)) - result = unpack_nr_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION, unpackedBufLen)){ + nfapi_nr_rach_indication_t* msg = (nfapi_nr_rach_indication_t*) pMessageHeader; + result = unpack_nr_rach_indication(&pReadPackedMessage, end, msg, config); + } else return -1; break; diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index 518b01864e..14c53b870b 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -852,7 +852,15 @@ typedef struct nfapi_vnf_p7_config * use the codec_config.deallocate function to release it at a future point */ int (*nrach_indication)(struct nfapi_vnf_p7_config* config, nfapi_nrach_indication_t* ind); - + + //The NR indication functions below copy uplink information received at the VNF into the UL info struct + + int (*nr_crc_indication)(nfapi_nr_crc_indication_t* ind); + int (*nr_rx_data_indication)(nfapi_nr_rx_data_indication_t* ind); + int (*nr_uci_indication)(nfapi_nr_uci_indication_t* ind); + int (*nr_rach_indication)(nfapi_nr_rach_indication_t* ind); + int (*nr_srs_indication)(nfapi_nr_srs_indication_t* ind); + /*! A callback for any vendor extension messages * \param config A pointer to the vnf p7 configuration * \param msg A data structure for the decoded vendor extention message allocated diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 936c434f44..d8d487aba2 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "vnf_p7.h" @@ -668,7 +669,6 @@ int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) { - nfapi_nr_dl_node_sync_t dl_node_sync; memset(&dl_node_sync, 0, sizeof(dl_node_sync)); @@ -1291,7 +1291,7 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { if(phy->in_sync == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); if(vnf_p7->_public.sync_indication) (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); @@ -1472,6 +1472,13 @@ void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } + else + { + if(vnf_p7->_public.nr_rx_data_indication) + { + (vnf_p7->_public.nr_rx_data_indication)(&ind); + } + } } } @@ -1491,6 +1498,13 @@ void vnf_handle_nr_crc_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } + else + { + if(vnf_p7->_public.nr_crc_indication) + { + (vnf_p7->_public.nr_crc_indication)(&ind); + } + } } } @@ -1510,7 +1524,13 @@ void vnf_handle_nr_srs_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } - + else + { + if(vnf_p7->_public.nr_srs_indication) + { + (vnf_p7->_public.nr_srs_indication)(&ind); + } + } } } @@ -1529,6 +1549,14 @@ void vnf_handle_nr_uci_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_ { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } + else + { + if(vnf_p7->_public.nr_uci_indication) + { + (vnf_p7->_public.nr_uci_indication)(&ind); + } + } + } } @@ -1547,6 +1575,13 @@ void vnf_handle_nr_rach_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); } + else + { + if(vnf_p7->_public.nr_rach_indication) + { + (vnf_p7->_public.nr_rach_indication)(&ind); + } + } } } @@ -1583,365 +1618,365 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 if(phy->in_sync == 0) { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); if(vnf_p7->_public.sync_indication) (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); } + printf("t1 = %d,t2 = %d, t3 = %d, t4 = %d. \n",ind.t1, ind.t2, ind.t3, t4); + //phy->in_sync = 1; - phy->in_sync = 1; + if(!(phy->filtered_adjust)) + { + phy->latency[phy->min_sync_cycle_count] = latency; - // if(!(phy->filtered_adjust)) - // { - // phy->latency[phy->min_sync_cycle_count] = latency; + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", + // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency); + } + else + { + phy->latency[phy->min_sync_cycle_count] = latency; - // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", - // // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, - // // tx_2_rx, pnf_proc_time, latency); - // } - // else - // { - // phy->latency[phy->min_sync_cycle_count] = latency; + //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) + { + if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) + { + // Only t2 wrap has occurred!!! + phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; + } + else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) + { + // Only t1 wrap has occurred + phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; + } + else + { + // Either no wrap or both have wrapped + phy->slot_offset = ind.t2 - ind.t1 - latency; + } - // //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) - // { - // if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) - // { - // // Only t2 wrap has occurred!!! - // phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; - // } - // else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) - // { - // // Only t1 wrap has occurred - // phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; - // } - // else - // { - // // Either no wrap or both have wrapped - // phy->slot_offset = ind.t2 - ind.t1 - latency; - // } + if (phy->slot_offset_filtered == 0) + { + phy->slot_offset_filtered = phy->slot_offset; + } + else + { + int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; + int32_t newOffsetShifted = phy->slot_offset << 5; - // if (phy->slot_offset_filtered == 0) - // { - // phy->slot_offset_filtered = phy->slot_offset; - // } - // else - // { - // int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; - // int32_t newOffsetShifted = phy->slot_offset << 5; + // 1/8 of new and 7/8 of old + phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; + } + } - // // 1/8 of new and 7/8 of old - // phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; - // } - // } + if(1) + { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); - // if(1) - // { - // struct timespec ts; - // clock_gettime(CLOCK_MONOTONIC, &ts); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + // ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + // (ind.t1previous_t1), (ind.t2previous_t2)); + } - // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", - // // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, - // // ind.t1, ind.t2, ind.t3, t4, - // // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, - // // (ind.t1previous_t1), (ind.t2previous_t2)); - // } + } - // } + if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) + { + phy->filtered_adjust = 0; + phy->zero_count=0; + phy->min_sync_cycle_count = 2; + phy->in_sync = 0; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); + } - // if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) - // { - // phy->filtered_adjust = 0; - // phy->zero_count=0; - // phy->min_sync_cycle_count = 2; - // phy->in_sync = 0; - // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); - // } + if(phy->min_sync_cycle_count) + phy->min_sync_cycle_count--; - // if(phy->min_sync_cycle_count) - // phy->min_sync_cycle_count--; + if(phy->min_sync_cycle_count == 0) + { + uint32_t curr_sfn = phy->sfn; + uint32_t curr_slot = phy->slot; + int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); - // if(phy->min_sync_cycle_count == 0) - // { - // uint32_t curr_sfn = phy->sfn; - // uint32_t curr_slot = phy->slot; - // int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + if(!phy->filtered_adjust) + { + int i = 0; + //phy->average_latency = 0; + for(i = 0; i < SYNC_CYCLE_COUNT; ++i) + { + phy->average_latency += phy->latency[i]; - // if(!phy->filtered_adjust) - // { - // int i = 0; - // //phy->average_latency = 0; - // for(i = 0; i < SYNC_CYCLE_COUNT; ++i) - // { - // phy->average_latency += phy->latency[i]; + } + phy->average_latency /= SYNC_CYCLE_COUNT; - // } - // phy->average_latency /= SYNC_CYCLE_COUNT; + phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); - // phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); - - // sfn_slot_dec += (phy->slot_offset / 500); + sfn_slot_dec += (phy->slot_offset / 500); - // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); - // } - // else - // { - // sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot + } + else + { + sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot - // } + } - // if(sfn_slot_dec < 0) - // { - // sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; - // } - // else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) - // { - // sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; - // } + if(sfn_slot_dec < 0) + { + sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; + } + else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) + { + sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; + } - // uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); - // uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); + uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); + uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); - // { - // phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); + { + phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); - // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); -// phy->previous_t1 = 0; -// phy->previous_t2 = 0; + phy->previous_t1 = 0; + phy->previous_t2 = 0; -// if(phy->previous_slot_offset_filtered > 0) -// { -// if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) -// { -// // pnf is getting futher ahead of vnf -// //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; -// phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; -// } -// else -// { -// // pnf is getting back in sync -// } -// } -// else if(phy->previous_slot_offset_filtered < 0) -// { -// if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) -// { -// // vnf is getting future ahead of pnf -// //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); -// phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; -// } -// else -// { -// // vnf is getting back in sync -// } -// } + if(phy->previous_slot_offset_filtered > 0) + { + if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) + { + // pnf is getting futher ahead of vnf + //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; + phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; + } + else + { + // pnf is getting back in sync + } + } + else if(phy->previous_slot_offset_filtered < 0) + { + if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) + { + // vnf is getting future ahead of pnf + //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); + phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; + } + else + { + // vnf is getting back in sync + } + } -// int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; -// int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; + int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; + int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; -// if(insync_minor_adjustment_1 == 0) -// insync_minor_adjustment_1 = 2; + if(insync_minor_adjustment_1 == 0) + insync_minor_adjustment_1 = 2; -// if(insync_minor_adjustment_2 == 0) -// insync_minor_adjustment_2 = 10; + if(insync_minor_adjustment_2 == 0) + insync_minor_adjustment_2 = 10; -// if(!phy->filtered_adjust) -// { -// if(phy->adjustment < 10) -// { -// phy->zero_count++; + if(!phy->filtered_adjust) + { + if(phy->adjustment < 10) + { + phy->zero_count++; -// if(phy->zero_count >= 10) -// { -// phy->filtered_adjust = 1; -// phy->zero_count = 0; + if(phy->zero_count >= 10) + { + phy->filtered_adjust = 1; + phy->zero_count = 0; -// NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); -// } -// } -// else -// { -// phy->zero_count = 0; -// } -// } -// else -// { -// // Fine level of adjustment -// if (phy->adjustment == 0) -// { -// if (phy->zero_count >= 10) -// { -// if(phy->in_sync == 0) -// { -// NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); + } + } + else + { + phy->zero_count = 0; + } + } + else + { + // Fine level of adjustment + if (phy->adjustment == 0) + { + if (phy->zero_count >= 10) + { + if(phy->in_sync == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); -// if(vnf_p7->_public.sync_indication) -// (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); -// } + if(vnf_p7->_public.sync_indication) + (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); + } -// phy->in_sync = 1; -// } -// else -// { -// phy->zero_count++; -// } + phy->in_sync = 1; + } + else + { + phy->zero_count++; + } -// if(phy->in_sync) -// { -// // in sync -// if(phy->slot_offset_filtered > 250) -// { -// // VNF is slow -// phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; -// phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); -// } -// else if(phy->slot_offset_filtered < -250) -// { -// // VNF is fast -// phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; -// phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); -// } -// else -// { -// phy->insync_minor_adjustment = 0; -// } + if(phy->in_sync) + { + // in sync + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; + phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; + phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); + } + else + { + phy->insync_minor_adjustment = 0; + } -// if(phy->insync_minor_adjustment != 0) -// { -// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", -// // phy->sfn, phy->slot, ind.header.phy_id, -// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, -// // phy->slot_offset_filtered, -// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, -// // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), -// // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), -// // phy->adjustment); -// } -// } -// } -// else -// { -// if (phy->in_sync) -// { -// if(phy->adjustment == 0) -// { -// } -// else if(phy->adjustment > 0) -// { -// // VNF is slow -// //if(phy->adjustment == 1) -// { -// // -// if(phy->slot_offset_filtered > 250) -// { -// // VNF is slow -// phy->insync_minor_adjustment = insync_minor_adjustment_2; -// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); -// } -// else if(phy->slot_offset_filtered < -250) -// { -// // VNF is fast -// phy->insync_minor_adjustment = -(insync_minor_adjustment_2); -// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); -// } + if(phy->insync_minor_adjustment != 0) + { + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, + // phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, + // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), + // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), + // phy->adjustment); + } + } + } + else + { + if (phy->in_sync) + { + if(phy->adjustment == 0) + { + } + else if(phy->adjustment > 0) + { + // VNF is slow + //if(phy->adjustment == 1) + { + // + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_2; + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_2); + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); + } -// } -// //else -// { -// // out of sync? -// } + } + //else + { + // out of sync? + } -// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", -// // phy->sfn, phy->slot, ind.header.phy_id, -// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, -// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, -// // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), -// // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), -// // phy->adjustment); + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, + // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), + // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), + // phy->adjustment); -// } -// else if(phy->adjustment < 0) -// { -// // VNF is fast -// //if(phy->adjustment == -1) -// { -// // -// if(phy->slot_offset_filtered > 250) -// { -// // VNF is slow -// phy->insync_minor_adjustment = insync_minor_adjustment_2; -// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); -// } -// else if(phy->slot_offset_filtered < -250) -// { -// // VNF is fast -// phy->insync_minor_adjustment = -(insync_minor_adjustment_2); -// phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); -// } -// } -// //else -// { -// // out of sync? -// } + } + else if(phy->adjustment < 0) + { + // VNF is fast + //if(phy->adjustment == -1) + { + // + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_2; + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_2); + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); + } + } + //else + { + // out of sync? + } -// // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", -// // phy->sfn, phy->slot, ind.header.phy_id, -// // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, -// // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); -// } + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); + } -// /* -// if (phy->adjustment > 10 || phy->adjustment < -10) -// { -// phy->zero_count++; // Add one to the getting out of sync counter -// } -// else -// { -// phy->zero_count = 0; // Small error - zero the out of sync counter -// } + /* + if (phy->adjustment > 10 || phy->adjustment < -10) + { + phy->zero_count++; // Add one to the getting out of sync counter + } + else + { + phy->zero_count = 0; // Small error - zero the out of sync counter + } -// if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync -// { -// NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); -// //pP7SockInfo->syncAchieved = 0; -// } -// */ -// } -// } -// } + if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); + //pP7SockInfo->syncAchieved = 0; + } + */ + } + } + } -// if(phy->in_sync == 0) -// { -// /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", -// ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), -// NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, -// phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", -// phy->zero_count, -// phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ + if(phy->in_sync == 0) + { + /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", + ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), + NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, + phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", + phy->zero_count, + phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ -// phy->sfn = new_sfn; -// phy->slot = new_slot; -// } -// } + phy->sfn = new_sfn; + phy->slot = new_slot; + } + } -// // reset for next cycle -// phy->previous_slot_offset_filtered = phy->slot_offset_filtered; -// phy->min_sync_cycle_count = 2; -// phy->slot_offset_filtered = 0; -// phy->slot_offset = 0; -// } -// else -// { -// phy->previous_t1 = ind.t1; -// phy->previous_t2 = ind.t2; -// } + // reset for next cycle + phy->previous_slot_offset_filtered = phy->slot_offset_filtered; + phy->min_sync_cycle_count = 2; + phy->slot_offset_filtered = 0; + phy->slot_offset = 0; + } + else + { + phy->previous_t1 = ind.t1; + phy->previous_t2 = ind.t2; + } } void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index f66919434e..5b36873e1c 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -422,7 +422,7 @@ struct timespec current_time; vnf_frame = curr->sfn; vnf_slot = curr->slot; struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); + clock_gettime(CLOCK_MONOTONIC, &curr_time); //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",vnf_frame,vnf_slot,curr_time.tv_sec,curr_time.tv_nsec); vnf_nr_sync(vnf_p7, curr); From ba2c28f6b1b47ddcafc4eafede881d4548de20f6 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Fri, 18 Jun 2021 19:26:56 +0530 Subject: [PATCH 099/185] PNF slot ticking fix --- nfapi/oai_integration/nfapi_vnf.c | 2 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 1 - nfapi/open-nFAPI/pnf/src/pnf_p7.c | 84 +++++++++++++++++++-- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 29 ++++--- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 3 +- 5 files changed, 92 insertions(+), 27 deletions(-) diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 8f30a091ab..80757089c6 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -596,7 +596,7 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { - //printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); + printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); if (sync==1 && nfapi_sync_var!=0) { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 3a90ca4363..de2316e4d7 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -307,7 +307,6 @@ static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePac static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { - printf("packing pdsch pdu. \n"); nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; // TODO: resolve the packaging of array (currently sending a single element) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index ab3b9196f1..b14e17d576 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -935,9 +935,9 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl // save the curren time, sfn and slot pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); - pnf_p7->sfn = sfn; + // pnf_p7->sfn = sfn; - pnf_p7->slot = slot; + // pnf_p7->slot = slot; @@ -3202,6 +3202,38 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) return 0; } +struct timespec pnf_timespec_add(struct timespec lhs, struct timespec rhs) +{ + struct timespec result; + + result.tv_sec = lhs.tv_sec + rhs.tv_sec; + result.tv_nsec = lhs.tv_nsec + rhs.tv_nsec; + + if(result.tv_nsec > 1e9) + { + result.tv_sec++; + result.tv_nsec-= 1e9; + } + + return result; +} + +struct timespec pnf_timespec_sub(struct timespec lhs, struct timespec rhs) +{ + struct timespec result; + if ((lhs.tv_nsec-rhs.tv_nsec)<0) + { + result.tv_sec = lhs.tv_sec-rhs.tv_sec-1; + result.tv_nsec = 1000000000+lhs.tv_nsec-rhs.tv_nsec; + } + else + { + result.tv_sec = lhs.tv_sec-rhs.tv_sec; + result.tv_nsec = lhs.tv_nsec-rhs.tv_nsec; + } + return result; +} + int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) { @@ -3279,6 +3311,23 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) } NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n"); + //Initializaing timing structures needed for slot ticking + + struct timespec slot_start; + clock_gettime(CLOCK_MONOTONIC, &slot_start); + + struct timespec pselect_start; + + struct timespec timeout; + timeout.tv_sec = 0; + timeout.tv_nsec = 500000; + + struct timespec slot_duration; + slot_duration.tv_sec = 0; + slot_duration.tv_nsec = 0.5e6; + + //Infinite loop + while(pnf_p7->terminate == 0) { fd_set rfds; @@ -3288,11 +3337,26 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) FD_ZERO(&rfds); FD_SET(pnf_p7->p7_sock, &rfds); - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 500; + clock_gettime(CLOCK_MONOTONIC, &pselect_start); - selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout); + //setting the timeout + + if((pselect_start.tv_sec > slot_start.tv_sec) || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) + { + // overran the end of the subframe we do not want to wait + timeout.tv_sec = 0; + timeout.tv_nsec = 0; + + //struct timespec overrun = pnf_timespec_sub(pselect_start, sf_start); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); + } + else + { + // still time before the end of the subframe wait + timeout = pnf_timespec_sub(slot_start, pselect_start); + } + + selectRetval = pselect(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout, NULL); uint32_t now_hr_time = pnf_get_current_time_hr(); @@ -3302,15 +3366,19 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(selectRetval == 0) { // timeout - //continue; + + //update slot start timing + slot_start = pnf_timespec_add(slot_start, slot_duration); + + //increment sfn/slot if (pnf_slot == 19) pnf_frame = (pnf_frame + 1) % 1024; pnf_slot = (pnf_slot + 1) % 20; pnf_p7->sfn = pnf_frame; pnf_p7->slot = pnf_slot; + struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); - //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",pnf_p7->sfn,pnf_p7->slot,curr_time.tv_sec,curr_time.tv_nsec); } else if (selectRetval == -1 && (errno == EINTR)) { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index d8d487aba2..e038f59217 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -1616,14 +1616,6 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 // divide by 2 using shift operator uint32_t latency = (tx_2_rx - pnf_proc_time) >> 1; - if(phy->in_sync == 0) - { - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); - - if(vnf_p7->_public.sync_indication) - (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); - } - printf("t1 = %d,t2 = %d, t3 = %d, t4 = %d. \n",ind.t1, ind.t2, ind.t3, t4); //phy->in_sync = 1; if(!(phy->filtered_adjust)) @@ -1675,17 +1667,24 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", - // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, - // ind.t1, ind.t2, ind.t3, t4, - // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, - // (ind.t1previous_t1), (ind.t2previous_t2)); + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + // ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + // (ind.t1previous_t1), (ind.t2previous_t2)); } } if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) - { + { struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + ind.t1, ind.t2, ind.t3, t4, + tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + (ind.t1previous_t1), (ind.t2previous_t2)); + phy->filtered_adjust = 0; phy->zero_count=0; phy->min_sync_cycle_count = 2; @@ -1961,7 +1960,7 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 phy->zero_count, phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ - phy->sfn = new_sfn; + phy->sfn = new_sfn; phy->slot = new_slot; } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 5b36873e1c..34318dcbcc 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -418,12 +418,11 @@ struct timespec current_time; { curr->slot++; } - //printf("Frame = %d, slot = %d in VNF main loop. n",curr->sfn,curr->slot); + //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); vnf_frame = curr->sfn; vnf_slot = curr->slot; struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); - //printf("SFN=%d, slot=%d, Curr_time=%d.%d \n",vnf_frame,vnf_slot,curr_time.tv_sec,curr_time.tv_nsec); vnf_nr_sync(vnf_p7, curr); curr = curr->next; From 9421c35a72b07390f9a45349ca7816b31392fe42 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 29 Jun 2021 08:49:48 +0530 Subject: [PATCH 100/185] Code cleanup --- executables/nr-ru.c | 6 +++--- nfapi/open-nFAPI/nfapi/src/nfapi.c | 2 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 360bd97287..0a042ba9b1 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -97,6 +97,7 @@ static int DEFBFW[] = {0x00007fff}; extern volatile int oai_exit; + extern void nr_phy_free_RU(RU_t *); extern void nr_phy_config_request(NR_PHY_Config_t *gNB); #include "executables/thread-common.h" @@ -708,7 +709,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -1299,7 +1300,6 @@ void *ru_thread( void *param ) { } // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices - while (!oai_exit) { // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. // They are set on the first rx/tx in the underly FH routines. @@ -1331,7 +1331,7 @@ void *ru_thread( void *param ) { // do RX front-end processing (frequency-shift, dft) if needed - int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); + int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx); if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) { if (ru->feprx) { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index 6ca64138f2..ba800c3634 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -189,7 +189,7 @@ uint8_t pull8(uint8_t **in, uint8_t *out, uint8_t *end) return 1; } else - { + { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s no space in buffer\n", __FUNCTION__); return 0; } diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 9159627286..aed8c2f8bb 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1466,7 +1466,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } } // cw loop corr_dB = dB_fixed64((uint64_t)corr); - LOG_I(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); + LOG_D(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); decodedPayload[0]=(uint64_t)cw_ML; } else { // polar coded case From 64a7191872cbe7d64a7b816274c0d46554acc300 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 29 Jun 2021 20:15:29 +0530 Subject: [PATCH 101/185] Cleanup --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 8 ++-- openair1/SCHED_NR/phy_frame_config_nr.c | 2 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 6 --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 46 ++++++++----------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 2 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 10 ++-- 6 files changed, 30 insertions(+), 44 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index aed8c2f8bb..8145cf893c 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -47,7 +47,6 @@ #include "PHY/NR_REFSIG/nr_refsig.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include "nfapi/oai_integration/vendor_ext.h" #include "T.h" @@ -87,8 +86,7 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - if (NFAPI_MODE == NFAPI_MODE_PNF) - gNB->pucch[0]->active = 0; //check if ture in monolithic mode + int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idrnti,id); @@ -169,6 +167,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + int nr_sequences; const uint8_t *mcs; @@ -1086,7 +1085,8 @@ void init_pucch2_luts() { void nr_decode_pucch2(PHY_VARS_gNB *gNB, int slot, nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, - nfapi_nr_pucch_pdu_t* pucch_pdu) { + nfapi_nr_pucch_pdu_t* pucch_pdu) { + int32_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; //pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 4c255e52aa..9be6780597 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -315,7 +315,7 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot if (cfg->cell_config.frame_duplex_type.value == FDD) { return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT ); } - + if (nr_frame%2 == 0) { for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 4a99b311db..83483f3a7f 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -532,7 +532,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); if (gNB->frame_parms.frame_type == TDD) - if(NFAPI_MODE != NFAPI_MODE_VNF) fill_ul_rb_mask(gNB, frame_rx, slot_rx); gNB_I0_measurements(gNB); @@ -547,8 +546,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { for (int i=0;ipucch[i]; if (pucch) { - if (NFAPI_MODE == NFAPI_MODE_PNF) - pucch->frame = frame_rx; if ((pucch->active == 1) && (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { @@ -615,9 +612,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { for (harq_pid=0;harq_pidharq_processes[harq_pid]; AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); - //printf("ulsch_harq->frame = %d, frame_rx = %d \n", ulsch_harq->frame, frame_rx); - if (NFAPI_MODE == NFAPI_MODE_PNF) - ulsch_harq->frame = frame_rx; if ((ulsch_harq->status == NR_ACTIVE) && (ulsch_harq->frame == frame_rx) && (ulsch_harq->slot == slot_rx) && diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index eacf4f54a9..8677b4931b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -121,38 +121,32 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; gNB->pdu_index[CC_idP] = 0; - if (NFAPI_MODE == NFAPI_MODE_VNF) - { - memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); - } - if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { // monolithic or PNF - DL_req[CC_idP].SFN = frameP; - DL_req[CC_idP].Slot = slotP; - DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; - DL_req[CC_idP].dl_tti_request_body.nGroup = 0; - //DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000; - memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); + DL_req[CC_idP].SFN = frameP; + DL_req[CC_idP].Slot = slotP; + DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; + DL_req[CC_idP].dl_tti_request_body.nGroup = 0; + //DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000; + memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); - UL_dci_req[CC_idP].SFN = frameP; - UL_dci_req[CC_idP].Slot = slotP; - UL_dci_req[CC_idP].numPdus = 0; + UL_dci_req[CC_idP].SFN = frameP; + UL_dci_req[CC_idP].Slot = slotP; + UL_dci_req[CC_idP].numPdus = 0; - /* advance last round's future UL_tti_req to be ahead of current frame/slot */ - future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024; - /* future_ul_tti_req->Slot is fixed! */ - future_ul_tti_req->n_pdus = 0; - future_ul_tti_req->n_ulsch = 0; - future_ul_tti_req->n_ulcch = 0; - future_ul_tti_req->n_group = 0; + /* advance last round's future UL_tti_req to be ahead of current frame/slot */ + future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024; + /* future_ul_tti_req->Slot is fixed! */ + future_ul_tti_req->n_pdus = 0; + future_ul_tti_req->n_ulsch = 0; + future_ul_tti_req->n_ulcch = 0; + future_ul_tti_req->n_group = 0; - /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., - * it walks over UL_tti_req_ahead in a circular fashion */ - gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][slotP]; + /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., + * it walks over UL_tti_req_ahead in a circular fashion */ + gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][slotP]; - TX_req[CC_idP].Number_of_PDUs = 0; + TX_req[CC_idP].Number_of_PDUs = 0; - } } /* void check_nr_ul_failure(module_id_t module_idP, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 46ccc8ac53..d5ae4aa4b3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1141,7 +1141,7 @@ int nr_acknack_scheduling(int mod_id, if(NFAPI_MODE == NFAPI_MODE_VNF){ gNB_MAC_INST *gNB = RC.nrmac[mod_id]; gNB->UL_tti_req_ahead[0][7].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 - gNB->UL_tti_req_ahead[0][8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 + gNB->[8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 gNB->UL_tti_req_ahead[0][9].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 1481865128..a789f0c34e 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -135,7 +135,6 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->tb_crc_status); /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - nr_rx_sdu(UL_info->module_id, UL_info->CC_id, UL_info->rx_ind.sfn, @@ -196,9 +195,8 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } handle_nr_rach(UL_info); - + handle_nr_uci(UL_info); - // clear HI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; handle_nr_ulsch(UL_info); @@ -215,7 +213,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { gNB_dlsch_ulsch_scheduler(module_id, (UL_info->frame+((UL_info->slot>(spf-1-sl_ahead))?1:0)) % 1024, (UL_info->slot+sl_ahead)%spf); - + ifi->CC_mask = 0; sched_info->module_id = module_id; sched_info->CC_id = CC_id; @@ -239,10 +237,10 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ifi->NR_Schedule_response(sched_info); } - LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n", + LOG_D(PHY,"NR_Schedule_response: SFN_SF:%d%d dl_pdus:%d\n", sched_info->frame, sched_info->slot, - sched_info->DL_req->dl_tti_request_body.nPDUs); + sched_info->DL_req->dl_tti_request_body.nPDUs); } } } From dc3f61b5c58f7ddad03116b8a5d003c3d6bcd791 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Sun, 4 Jul 2021 21:57:28 +0530 Subject: [PATCH 102/185] Build error fix, sync hardcode, UL indication called in every slot --- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 4 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 43 ++++++++++++------- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 4 ++ openair1/SCHED_NR/fapi_nr_l1.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 2 +- 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index b14e17d576..5c4dfa8c9f 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1561,7 +1561,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, // } struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); - printf("PNF SFN:%d, PNF slot:%d, VNF SFN:%d, VNF slot:%d, Curr time;%d.%d. \n",phy->sfn,phy->slot,sfn,slot,curr_time.tv_sec,curr_time.tv_nsec); + printf("PNF SFN:%d, PNF slot:%d, VNF SFN:%d, VNF slot:%d, SFN offset:%d, Curr time;%d.%d. \n",phy->sfn,phy->slot,sfn,slot, phy->sfn - sfn,curr_time.tv_sec,curr_time.tv_nsec); if(current_sfn_slot_dec <= recv_sfn_slot_dec + timing_window){ in_window = 1; NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); @@ -1578,7 +1578,7 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, }//Need to add more cases - + in_window = 0; // gokul return in_window; } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 34318dcbcc..d7e2fa5311 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -181,9 +181,11 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) slot_start = timespec_add(slot_start, slot_duration); NFAPI_TRACE(NFAPI_TRACE_INFO, "next slot will start at %d.%d\n", slot_start.tv_sec, slot_start.tv_nsec); - + struct timespec ref_time; + clock_gettime(CLOCK_MONOTONIC, &ref_time); + uint8_t setup_time; while(vnf_p7->terminate == 0) - { + { fd_set rfds; int maxSock = 0; FD_ZERO(&rfds); @@ -193,6 +195,10 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) FD_SET(vnf_p7->socket, &rfds); maxSock = vnf_p7->socket; + struct timespec curr_time; + clock_gettime(CLOCK_MONOTONIC, &curr_time); + setup_time = curr_time.tv_sec - ref_time.tv_sec; + clock_gettime(CLOCK_MONOTONIC, &pselect_start); //long millisecond = pselect_start.tv_nsec / 1e6; @@ -404,6 +410,19 @@ struct timespec current_time; clock_gettime(CLOCK_MONOTONIC, ¤t_time); // pselect timed out + if(setup_time > 10){ + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + } + while(curr != 0) { if (curr->slot == 19) @@ -418,13 +437,16 @@ struct timespec current_time; { curr->slot++; } - //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); + printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); vnf_frame = curr->sfn; vnf_slot = curr->slot; struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); - vnf_nr_sync(vnf_p7, curr); + //vnf_nr_sync(vnf_p7, curr); + + (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); //hardcoded sync + curr = curr->next; } send_mac_slot_indications(vnf_p7); @@ -435,19 +457,10 @@ struct timespec current_time; // have a p7 message if(FD_ISSET(vnf_p7->socket, &rfds)) { - + printf("P7 message received \n"); vnf_nr_p7_read_dispatch_message(vnf_p7); - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; - - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); + } } else diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 8145cf893c..27892aa417 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -48,6 +48,8 @@ #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "nfapi/oai_integration/vendor_ext.h" + #include "T.h" //#define DEBUG_NR_PUCCH_RX 1 @@ -86,6 +88,8 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { + if (NFAPI_MODE == NFAPI_MODE_PNF) + gNB->pucch[0]->active = 0; int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idUL_dci_req; frame_t frame = Sched_INFO->frame; sub_frame_t slot = Sched_INFO->slot; - + //printf("Inside nr_schedule_resp SFN:%d, slot:%d \n",Sched_INFO->frame, Sched_INFO->slot); AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n"); AssertFatal(RC.gNB[Mod_id]!=NULL,"RC.gNB[%d] is null\n",Mod_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index d5ae4aa4b3..46ccc8ac53 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1141,7 +1141,7 @@ int nr_acknack_scheduling(int mod_id, if(NFAPI_MODE == NFAPI_MODE_VNF){ gNB_MAC_INST *gNB = RC.nrmac[mod_id]; gNB->UL_tti_req_ahead[0][7].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 - gNB->[8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 + gNB->UL_tti_req_ahead[0][8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 gNB->UL_tti_req_ahead[0][9].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; } From 02f3fecfef5e0da9085390673d080430afa0d87e Mon Sep 17 00:00:00 2001 From: Mahesh Date: Mon, 5 Jul 2021 22:55:35 +0530 Subject: [PATCH 103/185] future_ul_tti hardcoding solved, other hardcodings commented out --- nfapi/nrNFAPI.md | 4 -- openair2/GNB_APP/gnb_app.c | 4 +- openair2/GNB_APP/gnb_config.c | 1 - openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 23 +++++++--- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 11 +++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 33 +++++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 46 +++++++++---------- 7 files changed, 56 insertions(+), 66 deletions(-) diff --git a/nfapi/nrNFAPI.md b/nfapi/nrNFAPI.md index b78a205e84..9b996bbedf 100644 --- a/nfapi/nrNFAPI.md +++ b/nfapi/nrNFAPI.md @@ -38,7 +38,3 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path To be updated. -## Notes -* If running for the first time on local branch, run in the following order - VNF then PNF. This is so that necessary files are generated for the UE to run. Stop this run (it's ok if it stops on its own due to an error). From every subsequent run follow the next bullet. -* In order to achieve synchronization between the VNF and PNF, and receive P7 messages within the timing window, the order in which we should run the modules on different terminals is UE->VNF->PNF. -* Currently downlink transmission from gNB to UE is partially functional and we are working on improving this. Uplink P7 messages are disabled and we will work on uplink integration after completing downlink. diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 66302d056b..da8d75c67b 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -218,7 +218,7 @@ void *gNB_app_task(void *args_p) //registered_gnb = 0; __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); } - +if (RC.nb_nr_inst > 0) { if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { @@ -240,7 +240,7 @@ void *gNB_app_task(void *args_p) itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); } - +} do { // Wait for a message itti_receive_msg (TASK_GNB_APP, &msg_p); diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 456d7cd6de..1942c9f934 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1410,7 +1410,6 @@ void NRRCConfig(void) { config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); RC.nb_nr_inst = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; - // Get num MACRLC instances config_getlist( &MACRLCParamList,NULL,0, NULL); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index a4c9a14aa3..7d9d55808a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -57,6 +57,8 @@ uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; +uint8_t first_sched_entry = 1; + void clear_mac_stats(gNB_MAC_INST *gNB) { memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t)); } @@ -367,6 +369,20 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); + + //first entry + if (NFAPI_MODE == NFAPI_MODE_VNF){ + if(first_sched_entry == 1) + { + for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = frame + 1; + else + gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; + } + first_sched_entry = 0; + } + } } @@ -410,13 +426,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedules the DCI for Uplink and subsequently PUSCH - if(NFAPI_MODE == NFAPI_MODE_VNF){ - gNB->UL_tti_req_ahead[0][7].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 - gNB->UL_tti_req_ahead[0][8].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 - gNB->UL_tti_req_ahead[0][9].SFN = frame;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 - gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; - } - nr_schedule_ulsch(module_idP, frame, slot); // This schedules the DCI for Downlink and PDSCH diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 7ffd544d10..17b1fc5233 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -834,8 +834,9 @@ void nr_schedule_ue_spec(module_id_t module_id, int8_t current_harq_pid = sched_pdsch->dl_harq_pid; if (current_harq_pid < 0) { /* PP has not selected a specific HARQ Process, get a new one */ - if (NFAPI_MODE == NFAPI_MODE_VNF) - sched_ctrl->available_dl_harq.head = 0; + // if (NFAPI_MODE == NFAPI_MODE_VNF) + // sched_ctrl->available_dl_harq.head = 0; + remove_front_nr_list(&sched_ctrl->available_dl_harq); current_harq_pid = sched_ctrl->available_dl_harq.head; AssertFatal(current_harq_pid >= 0, "no free HARQ process available for UE %d\n", @@ -852,9 +853,9 @@ void nr_schedule_ue_spec(module_id_t module_id, remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; - if (NFAPI_MODE == NFAPI_MODE_VNF) { - harq->is_waiting = false; - } + // if (NFAPI_MODE == NFAPI_MODE_VNF) { + // harq->is_waiting = false; + // } DevAssert(!harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[sched_pdsch->pucch_allocation]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 11bc09f7b3..93a2d87345 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -46,10 +46,6 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot]; - if (NFAPI_MODE == NFAPI_MODE_VNF){ - future_ul_tti_req->SFN = pucch->frame; - future_ul_tti_req->Slot = pucch->ul_slot; - } AssertFatal(future_ul_tti_req->SFN == pucch->frame && future_ul_tti_req->Slot == pucch->ul_slot, @@ -64,7 +60,7 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t)); future_ul_tti_req->n_pdus += 1; - LOG_D(MAC, + LOG_I(MAC, "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d on res %d\n", frame, slot, @@ -148,7 +144,7 @@ void nr_schedule_pucch(int Mod_idP, || frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) continue; - LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); + LOG_I(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id); memset(curr_pucch, 0, sizeof(*curr_pucch)); } @@ -519,9 +515,9 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; - if(NFAPI_MODE == NFAPI_MODE_VNF){ - curr_pucch->csi_bits = 0; curr_pucch->sr_flag = 0; curr_pucch->dai_c = 0; - } + // if(NFAPI_MODE == NFAPI_MODE_VNF){ + // curr_pucch->csi_bits = 0; curr_pucch->sr_flag = 0; curr_pucch->dai_c = 0; + // } AssertFatal(curr_pucch->csi_bits == 0 && !curr_pucch->sr_flag && curr_pucch->dai_c == 0, @@ -1141,23 +1137,16 @@ int nr_acknack_scheduling(int mod_id, __func__, pucch->csi_bits); /* if the currently allocated PUCCH of this UE is full, allocate it */ - if (NFAPI_MODE == NFAPI_MODE_VNF){ - pucch->sr_flag = 1; - pucch->dai_c = 1; - } + // if (NFAPI_MODE == NFAPI_MODE_VNF){ + // pucch->sr_flag = 1; + // pucch->dai_c = 1; + // } if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in * the same slot again */ const int f = pucch->frame; const int s = pucch->ul_slot; - if(NFAPI_MODE == NFAPI_MODE_VNF){ - gNB_MAC_INST *gNB = RC.nrmac[mod_id]; - gNB->UL_tti_req_ahead[0][7].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 7 - gNB->UL_tti_req_ahead[0][8].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 8 - gNB->UL_tti_req_ahead[0][9].SFN = f;//Added to set the UL_tti_req_ahead SFN in VNF mode for slot 9 - gNB->UL_tti_req[0] = &gNB->UL_tti_req_ahead[0][slot]; - } nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id); memset(pucch, 0, sizeof(*pucch)); pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; @@ -1194,8 +1183,8 @@ int nr_acknack_scheduling(int mod_id, get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); /* there is a HARQ. Check whether we can use it for this ACKNACK */ - if(NFAPI_MODE == NFAPI_MODE_VNF) - return 0; + // if(NFAPI_MODE == NFAPI_MODE_VNF) + // return 0; if (pucch->dai_c > 0) { /* this UE already has a PUCCH occasion */ DevAssert(pucch->frame == frame); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 9999581cf1..603f1ae3c7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1326,37 +1326,33 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) sched_ctrl->SR = false; int8_t harq_id = sched_pusch->ul_harq_pid; - if (NFAPI_MODE == NFAPI_MODE_VNF) - harq_id = 1; - else - { - if (harq_id < 0) { - /* PP has not selected a specific HARQ Process, get a new one */ - harq_id = sched_ctrl->available_ul_harq.head; - // if(NFAPI_MODE == NFAPI_MODE_VNF) - // harq_id = 1; - AssertFatal(harq_id >= 0, - "no free HARQ process available for UE %d\n", - UE_id); - remove_front_nr_list(&sched_ctrl->available_ul_harq); - sched_pusch->ul_harq_pid = harq_id; - } else { - /* PP selected a specific HARQ process. Check whether it will be a new - * transmission or a retransmission, and remove from the corresponding - * list */ - if (sched_ctrl->ul_harq_processes[harq_id].round == 0) - remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); - else - remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id); - } + + if (harq_id < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + harq_id = sched_ctrl->available_ul_harq.head; + // if(NFAPI_MODE == NFAPI_MODE_VNF) + // harq_id = 1; + AssertFatal(harq_id >= 0, + "no free HARQ process available for UE %d\n", + UE_id); + remove_front_nr_list(&sched_ctrl->available_ul_harq); + sched_pusch->ul_harq_pid = harq_id; + } else { + /* PP selected a specific HARQ process. Check whether it will be a new + * transmission or a retransmission, and remove from the corresponding + * list */ + if (sched_ctrl->ul_harq_processes[harq_id].round == 0) + remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); + else + remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id); } NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id]; DevAssert(!cur_harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); cur_harq->feedback_slot = sched_pusch->slot; cur_harq->is_waiting = true; - if (NFAPI_MODE == NFAPI_MODE_VNF) - cur_harq->is_waiting = 0; + // if (NFAPI_MODE == NFAPI_MODE_VNF) + // cur_harq->is_waiting = 0; int rnti_types[2] = { NR_RNTI_C, 0 }; From 74a092f73ac2dd6db45850e128eefe65849f34d5 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 6 Jul 2021 15:59:52 +0530 Subject: [PATCH 104/185] Documentation update, UL transmission --- doc/NFAPI_archi.md | 16 ++ nfapi/oai_integration/nfapi_pnf.c | 3 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 208 +++++++++++++---------- 3 files changed, 137 insertions(+), 90 deletions(-) diff --git a/doc/NFAPI_archi.md b/doc/NFAPI_archi.md index 61c66bd043..6bc906f494 100644 --- a/doc/NFAPI_archi.md +++ b/doc/NFAPI_archi.md @@ -100,14 +100,30 @@ if (Sched_INFO->TX_req->Number_of_PDUs > 0) ``` +```mermaid + +graph TD + pselect[VNF socket pselect] -- timed out : end of slot --> call_sched[Call Scheduler NR_UL_indication] -- oai_nfapi_***_req sends the DL p7 msg--> slot_inc[Increment sfn/slot]; + pselect[VNF socket pselect] -- UL p7 xyz msg recvd --> msg_recvd[Read message vnf_nr_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Handle Message vnf_handle_nr_xyz] --> fill_ul_info[Fill UL info struct with fn pointer vnf_p7->_public.nr_rx_xyz]; + fill_ul_info -- update pselect_timeout: next_slot_start - time_xyz_msg_recvd-->pselect; + slot_inc -- next slot --> pselect + +``` + ## P7 DL Reception at PNF Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message structures are filled in the PNF, and these are used further down the pipeline for processing. While receiving the DL P7 message, we check whether the message was received within a timing window from which it was sent. The duration of the window can be set by the user (set as a parameter for xnf in the p5 messages). A point to note is that the DL information must be received by the PNF within a timing window at least lesser than the duration of slot_ahead variable (timing_window <= slot_ahead * slot_duration). Ideally, it should be received within a duration significantly lesser than slot_ahead so that there is adequate time for PHY processing. +```mermaid +graph TB + pselect[PNF socket pselect] -- timed out : end of slot --> slot_inc[Increment sfn/slot]; + pselect[PNF socket pselect] -- DL p7 xyz msg recvd --> msg_recvd[Read message pnf_nr_nfapi_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Unpack Message pnf_handle_nr_xyz] --> fill_pnf_p7[Fill pnf_p7 global structure pnf_handle_nr_xyz] --Data from pnf_p7 struct copied to fapi structures using pnf_phy_***_req. Called every slot from oai_slot_ind-->pselect; + slot_inc -- next slot --> pselect +``` diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index ed0bafa300..d1a0ee5941 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1240,9 +1240,8 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE) { nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu=&dl_tti_pdu_list[i]; memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); - int SFN=sfn+2; //if(!&dl_tti_pdu->pdcch_pdu) - handle_nfapi_nr_pdcch_pdu(gNB, SFN, slot, &dl_tti_pdu->pdcch_pdu); + handle_nfapi_nr_pdcch_pdu(gNB, sfn, slot, &dl_tti_pdu->pdcch_pdu); //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) { diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index fa76fd00bc..edc3a7909b 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -53,53 +53,70 @@ extern uint16_t sf_ahead; extern uint16_t sl_ahead; void handle_nr_rach(NR_UL_IND_t *UL_info) { - - if (UL_info->rach_ind.number_of_pdus>0) { - LOG_D(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); - int npdus = UL_info->rach_ind.number_of_pdus; - for(int i = 0; i < npdus; i++) { - UL_info->rach_ind.number_of_pdus--; - if (UL_info->rach_ind.pdu_list[i].num_preamble>0) - AssertFatal(UL_info->rach_ind.pdu_list[i].num_preamble==1, - "More than 1 preamble not supported\n"); - - nr_initiate_ra_proc(UL_info->module_id, - UL_info->CC_id, - UL_info->rach_ind.sfn, - UL_info->rach_ind.slot, - UL_info->rach_ind.pdu_list[i].preamble_list[0].preamble_index, - UL_info->rach_ind.pdu_list[i].freq_index, - UL_info->rach_ind.pdu_list[i].symbol_index, - UL_info->rach_ind.pdu_list[i].preamble_list[0].timing_advance); + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->rach_ind.number_of_pdus>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_rach_indication(&UL_info->rach_ind); + UL_info->rach_ind.number_of_pdus = 0; + } + } + else{ + if (UL_info->rach_ind.number_of_pdus>0) { + LOG_D(MAC,"UL_info[Frame %d, Slot %d] Calling initiate_ra_proc RACH:SFN/SLOT:%d/%d\n",UL_info->frame,UL_info->slot, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); + int npdus = UL_info->rach_ind.number_of_pdus; + for(int i = 0; i < npdus; i++) { + UL_info->rach_ind.number_of_pdus--; + if (UL_info->rach_ind.pdu_list[i].num_preamble>0) + AssertFatal(UL_info->rach_ind.pdu_list[i].num_preamble==1, + "More than 1 preamble not supported\n"); + + nr_initiate_ra_proc(UL_info->module_id, + UL_info->CC_id, + UL_info->rach_ind.sfn, + UL_info->rach_ind.slot, + UL_info->rach_ind.pdu_list[i].preamble_list[0].preamble_index, + UL_info->rach_ind.pdu_list[i].freq_index, + UL_info->rach_ind.pdu_list[i].symbol_index, + UL_info->rach_ind.pdu_list[i].preamble_list[0].timing_advance); + } } } } void handle_nr_uci(NR_UL_IND_t *UL_info) -{ - const module_id_t mod_id = UL_info->module_id; - const frame_t frame = UL_info->frame; - const sub_frame_t slot = UL_info->slot; - int num_ucis = UL_info->uci_ind.num_ucis; - nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; +{ + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->uci_ind.num_ucis>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_uci_indication(&UL_info->uci_ind); + UL_info->uci_ind.num_ucis = 0; + } + } + else{ + const module_id_t mod_id = UL_info->module_id; + const frame_t frame = UL_info->frame; + const sub_frame_t slot = UL_info->slot; + int num_ucis = UL_info->uci_ind.num_ucis; + nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; - for (int i = 0; i < num_ucis; i++) { - switch (uci_list[i].pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: - LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__); - break; + for (int i = 0; i < num_ucis; i++) { + switch (uci_list[i].pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__); + break; - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; - handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); - break; - } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; + handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); + break; + } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; - handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); - break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; + handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); + break; + } } } } @@ -109,60 +126,75 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) void handle_nr_ulsch(NR_UL_IND_t *UL_info) { - if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { - for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { - for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { - // find crc_indication j corresponding rx_indication i - const nfapi_nr_rx_data_pdu_t *rx = &UL_info->rx_ind.pdu_list[i]; - const nfapi_nr_crc_t *crc = &UL_info->crc_ind.crc_list[j]; - LOG_D(PHY, - "UL_info->crc_ind.pdu_list[%d].rnti:%04x " - "UL_info->rx_ind.pdu_list[%d].rnti:%04x\n", - j, - crc->rnti, - i, - rx->rnti); + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->crc_ind.number_crcs>0) { + //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + oai_nfapi_nr_crc_indication(&UL_info->crc_ind); + UL_info->crc_ind.number_crcs = 0; + } - if (crc->rnti != rx->rnti) - continue; + if (UL_info->rx_ind.number_of_pdus>0) { + //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); + oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); + UL_info->rx_ind.number_of_pdus = 0; + } + } + else{ + if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { + for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { + for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { + // find crc_indication j corresponding rx_indication i + const nfapi_nr_rx_data_pdu_t *rx = &UL_info->rx_ind.pdu_list[i]; + const nfapi_nr_crc_t *crc = &UL_info->crc_ind.crc_list[j]; + LOG_D(PHY, + "UL_info->crc_ind.pdu_list[%d].rnti:%04x " + "UL_info->rx_ind.pdu_list[%d].rnti:%04x\n", + j, + crc->rnti, + i, + rx->rnti); - LOG_D(MAC, - "%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n", - UL_info->frame, - UL_info->slot, - crc->tb_crc_status ? "error" : "ok", - crc->tb_crc_status); + if (crc->rnti != rx->rnti) + continue; - /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot, - rx->rnti, - crc->tb_crc_status ? NULL : rx->pdu, - rx->pdu_length, - rx->timing_advance, - rx->ul_cqi, - rx->rssi); - handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); - break; - } // for (j=0;jcrc_ind.number_crcs;j++) - } // for (i=0;irx_ind.number_of_pdus;i++) + LOG_D(MAC, + "%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n", + UL_info->frame, + UL_info->slot, + crc->tb_crc_status ? "error" : "ok", + crc->tb_crc_status); - UL_info->crc_ind.number_crcs = 0; - UL_info->rx_ind.number_of_pdus = 0; - } else if (UL_info->rx_ind.number_of_pdus != 0 - || UL_info->crc_ind.number_crcs != 0) { - LOG_E(PHY, - "hoping not to have mis-match between CRC ind and RX ind - " - "hopefully the missing message is coming shortly " - "rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n", - UL_info->rx_ind.number_of_pdus, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot, - UL_info->crc_ind.number_crcs, - UL_info->rx_ind.sfn, - UL_info->rx_ind.slot); + /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ + nr_rx_sdu(UL_info->module_id, + UL_info->CC_id, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + rx->rnti, + crc->tb_crc_status ? NULL : rx->pdu, + rx->pdu_length, + rx->timing_advance, + rx->ul_cqi, + rx->rssi); + handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); + break; + } // for (j=0;jcrc_ind.number_crcs;j++) + } // for (i=0;irx_ind.number_of_pdus;i++) + + UL_info->crc_ind.number_crcs = 0; + UL_info->rx_ind.number_of_pdus = 0; + } else if (UL_info->rx_ind.number_of_pdus != 0 + || UL_info->crc_ind.number_crcs != 0) { + LOG_E(PHY, + "hoping not to have mis-match between CRC ind and RX ind - " + "hopefully the missing message is coming shortly " + "rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n", + UL_info->rx_ind.number_of_pdus, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + UL_info->crc_ind.number_crcs, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot); + } } } From c9c1df5e32c4394410a49eda807089b7c882fab0 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 20 Jul 2021 08:29:55 +0530 Subject: [PATCH 105/185] fix tdd slot config pack/unpack --- nfapi/open-nFAPI/nfapi/src/nfapi_p5.c | 35 +++++++++++-------- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 4 +-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 1 - 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index 8aea9f590c..8072b5f530 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -860,9 +860,14 @@ static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_ static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { - printf("\n\nEntering pack_config_request\n"); + nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; + for(int i = 0; i<40; i++){ //packing tdd slot config + for(int symbol = 0; symbol<14;symbol++){ + push8(pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[symbol].slot_config.value, ppWritePackedMsg,end); + } + } return (push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && pack_tlv(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && @@ -884,10 +889,10 @@ static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uin pack_tlv(NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && pack_tlv(NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), ppWritePackedMsg, end, &pack_uint8_tlv_value) && pack_tlv(NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), ppWritePackedMsg, end, &pack_uint8_tlv_value) && pack_tlv(NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), ppWritePackedMsg, end, &pack_uint8_tlv_value) && @@ -903,11 +908,6 @@ static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uin pack_tlv(NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && pack_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - pack_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - - //pack_tlv(NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && - //pack_tlv(NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && - //pack_tlv(NFAPI_NR_NFAPI_NRARFCN_TAG, &(pNfapiMsg->nfapi_config.nrarfcn), ppWritePackedMsg, end, &pack_uint32_tlv_value) && pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && @@ -2070,12 +2070,18 @@ static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, { nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; - pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t*) malloc(20*sizeof(nfapi_nr_max_tdd_periodicity_t)); + pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t*) malloc(40*sizeof(nfapi_nr_max_tdd_periodicity_t)); + for(int i=0;i<40;i++) - pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t*) malloc(14*sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); + pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t*) malloc(14*sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); pNfapiMsg->prach_config.num_prach_fd_occasions_list=(nfapi_nr_num_prach_fd_occasions_t *) malloc(sizeof(nfapi_nr_num_prach_fd_occasions_t)); + for(int i = 0; i < 40; i++){ //unpacking tdd slot config + for(int symbol = 0; symbol<14;symbol++){ + pull8(ppReadPackedMsg,&pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[symbol].slot_config.value, end); + } + } unpack_tlv_t unpack_fns[] = { { NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), &unpack_uint16_tlv_value}, @@ -2111,8 +2117,6 @@ static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, { NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), &unpack_uint8_tlv_value}, { NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), &unpack_uint8_tlv_value}, { NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value}, - { NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), &unpack_uint8_tlv_value}, - { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), &unpack_ipv4_address_value}, { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), &unpack_ipv6_address_value}, { NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), &unpack_uint16_tlv_value}, { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value}, @@ -2122,9 +2126,10 @@ static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), &unpack_uint8_tlv_value}, { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), &unpack_uint8_tlv_value}, }; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); - + } static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index e038f59217..443ccc3d49 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -2039,8 +2039,8 @@ void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnslot_delta,NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot),NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot)) ; // Panos: Careful here!!! Modification of the original nfapi-code - // vnf_p7->p7_connections[0].sfn = ind.last_sfn; - // vnf_p7->p7_connections[0].slot = ind.last_slot; + vnf_p7->p7_connections[0].sfn = ind.last_sfn; + vnf_p7->p7_connections[0].slot = ind.last_slot; } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 17b1fc5233..888c55ca7e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -836,7 +836,6 @@ void nr_schedule_ue_spec(module_id_t module_id, /* PP has not selected a specific HARQ Process, get a new one */ // if (NFAPI_MODE == NFAPI_MODE_VNF) // sched_ctrl->available_dl_harq.head = 0; - remove_front_nr_list(&sched_ctrl->available_dl_harq); current_harq_pid = sched_ctrl->available_dl_harq.head; AssertFatal(current_harq_pid >= 0, "no free HARQ process available for UE %d\n", From 196213b6c2457cc3b1a178b252d55e4a35c8ff56 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 23 Jul 2021 16:02:29 +0200 Subject: [PATCH 106/185] fixing a compilation warning in enb_app --- openair2/ENB_APP/enb_app.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 9f134f826e..2e6c94540d 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -53,7 +53,6 @@ #include "openair1/PHY/INIT/phy_init.h" extern unsigned char NB_eNB_INST; -#include extern RAN_CONTEXT_t RC; # define ENB_REGISTER_RETRY_DELAY 10 From 09665eeb76760ff9f2dd52f2956aa0cc20d8405a Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 26 Jul 2021 15:04:34 +0200 Subject: [PATCH 107/185] Revert "Put back cell_group_config when do-ra" This reverts commit bb646da064ad4869b39eb3c042a46fcfd0bd4c69. --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 22 ++++------------- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 33 ++++++++++---------------- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index a2befdbe1a..6dfc9ae220 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -368,7 +368,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, mac->frequency_range = band<100?FR1:FR2; lte_frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); - + // cell config cfg->cell_config.phy_cell_id = *scc->physCellId; @@ -667,26 +667,12 @@ int nr_rrc_mac_config_req_ue( // Setup the SSB to Rach Occasions mapping according to the config build_ssb_to_ro_map(mac); } - else if (cell_group_config != NULL){ + else if (cell_group_config != NULL ){ LOG_I(MAC,"Applying CellGroupConfig from gNodeB\n"); mac->cg = cell_group_config; mac->servCellIndex = cell_group_config->spCellConfig->servCellIndex ? *cell_group_config->spCellConfig->servCellIndex : 0; - if(get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra==1) { - config_control_ue(mac); - if (cell_group_config->spCellConfig->reconfigurationWithSync) { - if (cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated) { - ra->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; - } - mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; - config_common_ue(mac,module_id,cc_idP); - mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; - LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); - } - - // Setup the SSB to Rach Occasions mapping according to the config - build_ssb_to_ro_map(mac); - } - + // config_control_ue(mac); + // config_common_ue(mac,module_id,cc_idP); /* if(mac_cell_group_configP != NULL){ if(mac_cell_group_configP->drx_Config != NULL ){ diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 91579d750f..76f764ec37 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -53,26 +53,19 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { nr_ue_mac_inst = (NR_UE_MAC_INST_t *)calloc(sizeof(NR_UE_MAC_INST_t),NB_NR_UE_MAC_INST); for (int j=0;jscell_group_config || rrc_inst->cell_group_config)) { - if(rrc_inst->scell_group_config) { - nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,rrc_inst->scell_group_config); - //if (IS_SOFTMODEM_NOS1){ - // AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); - // nr_pdcp_layer_init(); - // nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); - //} - } else if (rrc_inst->cell_group_config) { - nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,rrc_inst->cell_group_config,NULL); - AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); - if (IS_SOFTMODEM_NOS1){ - pdcp_layer_init(); - nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); - } - } + if (rrc_inst && rrc_inst->scell_group_config) { + + nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,rrc_inst->scell_group_config); + + // if (IS_SOFTMODEM_NOS1){ + //if (1) { + // AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); + // nr_pdcp_layer_init(); + //nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); + //} // Allocate memory for ul_config_request in the mac instance. This is now a pointer and will // point to a list of structures (one for each UL slot) to store PUSCH scheduling parameters @@ -84,8 +77,8 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { LOG_D(MAC, "Initializing ul_config_request. num_slots_ul = %d\n", num_slots_ul); nr_ue_mac_inst->ul_config_request = (fapi_nr_ul_config_request_t *)calloc(num_slots_ul, sizeof(fapi_nr_ul_config_request_t)); } - - } else { + } + else { LOG_I(MAC,"Running without CellGroupConfig\n"); nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,NULL); if(get_softmodem_params()->sa == 1) { From 1d66b5c41516e1d87a8a4956b68c0907420a03bb Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 26 Jul 2021 16:08:52 +0200 Subject: [PATCH 108/185] attempting to fix wrong implementation in NSA UE configuration --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 4 +- openair2/RRC/NR_UE/rrc_UE.c | 100 +++++++++++++------------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 6dfc9ae220..6f9e36d047 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -316,7 +316,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, // carrier config LOG_D(MAC, "Entering UE Config Common\n"); - AssertFatal(scc==NULL,"scc cannot be null\n"); + AssertFatal(scc!=NULL,"scc cannot be null\n"); if (scc) { cfg->carrier_config.dl_bandwidth = config_bandwidth(scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, @@ -658,7 +658,7 @@ int nr_rrc_mac_config_req_ue( ra->rach_ConfigDedicated = scell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; } mac->scc = scell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; - mac->physCellId = *mac->scc->physCellId; + mac->physCellId = *mac->scc->physCellId; config_common_ue(mac,module_id,cc_idP); mac->crnti = scell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 6bcddf7369..f272c16017 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -201,42 +201,38 @@ extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * con struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); // from LTE-RRC DL-DCCH RRCConnectionReconfiguration nr-secondary-cell-group-config (encoded) -int8_t nr_rrc_ue_decode_secondary_cellgroup_config( - const module_id_t module_id, - const uint8_t *buffer, - const uint32_t size ){ +int8_t nr_rrc_ue_decode_secondary_cellgroup_config(const module_id_t module_id, + const uint8_t *buffer, + const uint32_t size){ - NR_CellGroupConfig_t *cell_group_config = NULL; - uint32_t i; + NR_CellGroupConfig_t *cell_group_config = NULL; + uint32_t i; - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cell_group_config, - (uint8_t *)buffer, - size ); + asn_dec_rval_t dec_rval = uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, + (void **)&cell_group_config, + (uint8_t *)buffer, + size, 0, 0); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - printf("NR_CellGroupConfig decode error\n"); - for (i=0; imac_CellGroupConfig, cell_group_config->physicalCellGroupConfig, cell_group_config->spCellConfig ); - - return 0; + return 0; } int8_t nr_rrc_ue_process_RadioBearerConfig(NR_RadioBearerConfig_t *RadioBearerConfig){ @@ -262,25 +258,33 @@ int8_t nr_rrc_ue_process_rrcReconfiguration(const module_id_t module_id, NR_RRCR } } if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup != NULL){ - NR_CellGroupConfig_t *cellGroupConfig = NULL; - uper_decode(NULL, - &asn_DEF_NR_CellGroupConfig, //might be added prefix later - (void **)&cellGroupConfig, - (uint8_t *)rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->buf, - rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->size, 0, 0); - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)cellGroupConfig); + if(get_softmodem_params()->sa) { - if(NR_UE_rrc_inst[module_id].cell_group_config == NULL){ - // first time receive the configuration, just use the memory allocated from uper_decoder. TODO this is not good implementation, need to maintain RRC_INST own structure every time. - NR_UE_rrc_inst[module_id].cell_group_config = cellGroupConfig; - nr_rrc_ue_process_scg_config(module_id,cellGroupConfig); - }else{ - // after first time, update it and free the memory after. - SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)NR_UE_rrc_inst[module_id].cell_group_config, 0); - NR_UE_rrc_inst[module_id].cell_group_config = cellGroupConfig; - nr_rrc_ue_process_scg_config(module_id,cellGroupConfig); + NR_CellGroupConfig_t *cellGroupConfig = NULL; + uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, //might be added prefix later + (void **)&cellGroupConfig, + (uint8_t *)rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->buf, + rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->size, 0, 0); + + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)cellGroupConfig); + + if(NR_UE_rrc_inst[module_id].cell_group_config == NULL){ + // first time receive the configuration, just use the memory allocated from uper_decoder. TODO this is not good implementation, need to maintain RRC_INST own structure every time. + NR_UE_rrc_inst[module_id].cell_group_config = cellGroupConfig; + nr_rrc_ue_process_scg_config(module_id,cellGroupConfig); + }else{ + // after first time, update it and free the memory after. + SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)NR_UE_rrc_inst[module_id].cell_group_config, 0); + NR_UE_rrc_inst[module_id].cell_group_config = cellGroupConfig; + nr_rrc_ue_process_scg_config(module_id,cellGroupConfig); + } } + else + nr_rrc_ue_decode_secondary_cellgroup_config(module_id, + rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->buf, + rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->secondaryCellGroup->size); } if(rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration->measConfig != NULL){ if(NR_UE_rrc_inst[module_id].meas_config == NULL){ @@ -317,7 +321,7 @@ int8_t nr_rrc_ue_process_meas_config(NR_MeasConfig_t *meas_config){ int8_t nr_rrc_ue_process_scg_config(const module_id_t module_id, NR_CellGroupConfig_t *cell_group_config){ int i; - if(NR_UE_rrc_inst[module_id].cell_group_config==NULL){ + if(cell_group_config==NULL){ // initial list if(cell_group_config->spCellConfig != NULL){ if(cell_group_config->spCellConfig->spCellConfigDedicated != NULL){ From 201271846cc0f5f20500f5832455d96e511fc07d Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 26 Jul 2021 19:24:31 +0200 Subject: [PATCH 109/185] some fixes for NSA UE --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 32 +++++++++++++------ .../NR_MAC_UE/nr_ue_dci_configuration.c | 14 ++++---- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- openair2/RRC/NR/rrc_gNB_reconfig.c | 8 +++-- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 314951a63b..19e4383d27 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -82,20 +82,32 @@ void init_RA(module_id_t mod_id, prach_resources->RA_SCALING_FACTOR_BI = 1; struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList; - NR_SearchSpaceId_t ss_id = 0; + NR_SearchSpaceId_t *ra_ss; + NR_SearchSpaceId_t ss_id = -1; NR_SearchSpace_t *ss = NULL; - if(mac->scc) { - commonSearchSpaceList = mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - ss_id = *mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + + if(mac->scc_SIB) { + commonSearchSpaceList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ss_id = *mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->ra_SearchSpace; } - else { - if(mac->scc_SIB) { - commonSearchSpaceList = mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - ss_id = *mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + else{ + if (mac->scc) { + NR_SearchSpaceId_t *ra_ss = mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + if (ra_ss) { + commonSearchSpaceList = mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ss_id = *mac->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } + } + if (ss_id < 0) { + ra_ss = mac->DLbwp[0]->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + if (ra_ss) { + commonSearchSpaceList = mac->DLbwp[0]->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + ss_id = *mac->DLbwp[0]->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace; + } } - else - AssertFatal(1==0,"Both scc and scc_SIB are null\n"); } + + AssertFatal(ss_id>-1,"Didn't find ra-SearchSpace\n"); AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n"); // Common searchspace list for (int i = 0; i < commonSearchSpaceList->list.count; i++) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index f1431dcbd9..9ff0be318c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -430,11 +430,13 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl } else { // use coreset0/ss0 NR_SearchSpace_t *ss0 = mac->search_space_zero; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15; - rel15->num_dci_options = 1; - rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; - config_dci_pdu(mac, rel15, dl_config, NR_RNTI_C , -1); - fill_dci_search_candidates(ss0, rel15); - dl_config->number_pdus = 1; + if(ss0) { + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15; + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_C , -1); + fill_dci_search_candidates(ss0, rel15); + dl_config->number_pdus = 1; + } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index d4475cc53d..d17c1ecdf7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -545,7 +545,7 @@ void nr_initiate_ra_proc(module_id_t module_idP, if (ra->CellGroup && ra->CellGroup->spCellConfig && ra->CellGroup->spCellConfig->spCellConfigDedicated && ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList) { ra->bwp_id = 1; - bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; + bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1); diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index d2ca610e16..bf83e13af2 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -460,9 +460,11 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list,ss); - - bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1)); - *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=0; + bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=NULL; + if(get_softmodem_params()->sa) { + bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1)); + *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1=0; + } bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->pagingSearchSpace=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)); From bf53625dacb0b8e2c74cd0149c72bb0c4b120314 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Fri, 23 Apr 2021 23:36:19 +0100 Subject: [PATCH 110/185] Fix selection of Msg3 for CFRA at UE --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 20cafa8389..7c5cb27213 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -953,8 +953,8 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = 0; } else { - if ( (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator || - mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id]==1)){ + if ((mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator || + mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id]==1) && ra->ra_state == RA_SUCCEEDED){ // Getting IP traffic to be transmitted data_existing = nr_ue_get_sdu(mod_id, From fab6ec4579ece1ea1719a8999213ee2184e7e7fa Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 27 Jul 2021 11:12:02 +0200 Subject: [PATCH 111/185] fix(ci): adding detection of timed-out run on the physims on cluster Signed-off-by: Raphael Defosseux --- ci-scripts/cls_physim1.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_physim1.py b/ci-scripts/cls_physim1.py index 1c82526831..131aa01c4c 100644 --- a/ci-scripts/cls_physim1.py +++ b/ci-scripts/cls_physim1.py @@ -245,7 +245,7 @@ class PhySim: isFinished = False # doing a deep copy! tmpPodNames = podNames.copy() - while(count < 28 and isFinished == False): + while(count < 32 and isFinished == False): time.sleep(60) for podName in tmpPodNames: mySSH.command2(f'oc logs --tail=1 {podName} 2>&1', 6, silent=True) @@ -257,6 +257,8 @@ class PhySim: count += 1 if isFinished: logging.debug('\u001B[1m PhySim test is Complete\u001B[0m') + else: + logging.error('\u001B[1m PhySim test Timed-out!\u001B[0m') # Getting the logs of each executables running in individual pods for podName in podNames: @@ -279,15 +281,18 @@ class PhySim: mySSH.command('oc logout', '\$', 6) mySSH.close() self.AnalyzeLogFile_phySim(HTML) - if self.testStatus: + if self.testStatus and isFinished: HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) HTML.CreateHtmlTestRowPhySimTestResult(self.testSummary,self.testResult) logging.info('\u001B[1m Physical Simulator Pass\u001B[0m') else: RAN.prematureExit = True - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) + if isFinished: + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) + else: + HTML.CreateHtmlTestRow('Some test(s) timed-out!', 'KO', CONST.ALL_PROCESSES_OK) HTML.CreateHtmlTestRowPhySimTestResult(self.testSummary,self.testResult) - logging.info('\u001B[1m Physical Simulator Fail\u001B[0m') + logging.error('\u001B[1m Physical Simulator Fail\u001B[0m') def AnalyzeLogFile_phySim(self, HTML): lIpAddr = self.eNBIPAddress From ac4ae0e0fdac7ca638fe205adf57619b0a90826e Mon Sep 17 00:00:00 2001 From: spclab Date: Tue, 27 Jul 2021 15:10:54 +0530 Subject: [PATCH 112/185] Hardcodings removed fully, system runs but unstable --- executables/nr-gnb.c | 17 ++- nfapi/oai_integration/nfapi_pnf.c | 34 +++--- nfapi/oai_integration/nfapi_vnf.c | 16 ++- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 3 +- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 109 +++--------------- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 5 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 49 +++++--- openair1/PHY/NR_TRANSPORT/nr_dci_tools.c | 8 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 4 +- openair1/SCHED_NR/fapi_nr_l1.c | 8 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 10 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 7 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 5 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 6 +- 14 files changed, 110 insertions(+), 171 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 7c74cab8ff..166ebd69b6 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -133,7 +133,7 @@ void tx_func(void *param) { } void rx_func(void *param) { - + processingData_L1_t *info = (processingData_L1_t *) param; PHY_VARS_gNB *gNB = info->gNB; int frame_rx = info->frame_rx; @@ -146,15 +146,12 @@ void rx_func(void *param) { start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* - // NFAPI not yet supported for NR - this code has to be revised + if (NFAPI_MODE == NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick - //add_subframe(&frame, &subframe, 4); - //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); - //LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe); + //LOG_D(PHY, "oai_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); start_meas(&nfapi_meas); - // oai_subframe_ind(frame_rx, slot_rx); - oai_slot_ind(frame_rx, slot_rx); + oai_slot_ind(frame_tx, slot_tx); stop_meas(&nfapi_meas); /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| @@ -217,6 +214,7 @@ void rx_func(void *param) { gNB->pucch[j]->pucch_pdu.rnti = 0; pucch_removed++; } + #if 0 for (j = 0; j < NUMBER_OF_NR_PDCCH_MAX; j++) gNB->pdcch_pdu[j].frame = -1; @@ -258,8 +256,7 @@ void rx_func(void *param) { // Call the scheduler - if (NFAPI_MODE == NFAPI_MONOLITHIC){ - start_meas(&gNB->ul_indication_stats); + start_meas(&gNB->ul_indication_stats); pthread_mutex_lock(&gNB->UL_INFO_mutex); gNB->UL_INFO.frame = frame_rx; gNB->UL_INFO.slot = slot_rx; @@ -268,7 +265,7 @@ void rx_func(void *param) { gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); stop_meas(&gNB->ul_indication_stats); - } + notifiedFIFO_elt_t *res; diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index d1a0ee5941..0783aa26b3 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1150,14 +1150,13 @@ int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; if (proc ==NULL) proc = &gNB->proc.L1_proc; - + //int slot_tx = req->Slot + 6; //Ref for PNF is slot_rx, so align slot number with tx thread before passing UL_DCI info for (int i=0; inumPdus; i++) { //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); if (req->ul_dci_pdu_list[i].PDUType == 0) { //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_DCI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); nfapi_nr_ul_dci_request_pdus_t *ul_dci_req_pdu = &req->ul_dci_pdu_list[i]; - int SFN=req->SFN+2; - handle_nfapi_nr_ul_dci_pdu(gNB, SFN, req->Slot, ul_dci_req_pdu); + handle_nfapi_nr_ul_dci_pdu(gNB, req->SFN, req->Slot, ul_dci_req_pdu); } else { LOG_E(PHY,"[PNF] UL_DCI_REQ sfn_slot:%d PDU[%d] - unknown pdu type:%d\n", NFAPI_SFNSLOT2DEC(req->SFN, req->Slot), i, req->ul_dci_pdu_list[i].PDUType); @@ -1217,21 +1216,21 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, int sfn = req->SFN; int slot = req->Slot; - + //int slot_tx = slot + 6; // ref for PNF is slot_rx, so increment by slot ahead struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; if (proc==NULL) proc = &gNB->proc.L1_proc; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu_list = req->dl_tti_request_body.dl_tti_pdu_list; if (req->dl_tti_request_body.nPDUs) - NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d; sfn:%d, slot:%d, nGroup:%u, nPDUs: %u, nUE: %u, PduIdx: %u,\n", - __FUNCTION__, proc->frame_tx, proc->slot_tx, proc->frame_rx, proc->slot_rx, // TODO: change subframes to slot - req->SFN, - req->Slot, - req->dl_tti_request_body.nGroup, - req->dl_tti_request_body.nPDUs, - req->dl_tti_request_body.nUe, - req->dl_tti_request_body.PduIdx); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d; sfn:%d, slot:%d, nGroup:%u, nPDUs: %u, nUE: %u, PduIdx: %u,\n", + // __FUNCTION__, proc->frame_tx, proc->slot_tx, proc->frame_rx, proc->slot_rx, // TODO: change subframes to slot + // req->SFN, + // req->Slot, + // req->dl_tti_request_body.nGroup, + // req->dl_tti_request_body.nPDUs, + // req->dl_tti_request_body.nUe, + // req->dl_tti_request_body.PduIdx); for (int i=0; idl_tti_request_body.nPDUs; i++) { // TODO: enable after adding gNB PDCCH: @@ -1435,13 +1434,10 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_tti_request_t *req) { - // if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", - // __FUNCTION__, - // NFAPI_SFNSF2DEC(req->sfn_sf), - // req->ul_config_request_body.number_of_pdus, - // req->ul_config_request_body.rach_prach_frequency_resources, - // req->ul_config_request_body.srs_present - // ); + LOG_D(PHY,"[PNF] UL_TTI_REQ recvd, writing into structs, SFN/slot:%d.%d pdu:%d \n", + req->SFN,req->Slot, + req->n_pdus + ); if (RC.ru == 0) { return -1; diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 80757089c6..e86c932483 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -596,7 +596,7 @@ extern pthread_mutex_t nfapi_sync_mutex; extern int nfapi_sync_var; int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { - printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); + //printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); if (sync==1 && nfapi_sync_var!=0) { @@ -1019,7 +1019,9 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); - ind->number_crcs = 1; + + gNB->UL_INFO.crc_ind = *ind; + if (ind->number_crcs > 0) gNB->UL_INFO.crc_ind.crc_list = malloc(sizeof(nfapi_nr_crc_t)*ind->number_crcs); @@ -1035,6 +1037,8 @@ int phy_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.rx_ind = *ind; + if (ind->number_of_pdus > 0) gNB->UL_INFO.rx_ind.pdu_list = malloc(sizeof(nfapi_nr_rx_data_pdu_t)*ind->number_of_pdus); @@ -1051,12 +1055,14 @@ int phy_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.uci_ind = *ind; + if (ind->num_ucis > 0) gNB->UL_INFO.uci_ind.uci_list = malloc(sizeof(nfapi_nr_uci_t)*ind->num_ucis); for (int i=0; inum_ucis; i++) memcpy(&gNB->UL_INFO.uci_ind.uci_list[i], &ind->uci_list[i], sizeof(ind->uci_list[0])); - + //printf("UCI ind written to UL_info: num_ucis: %d, PDU_type : %d. \n", ind->num_ucis, ind->uci_list[0].pdu_type); pthread_mutex_unlock(&gNB->UL_INFO_mutex); return 1; @@ -1066,6 +1072,8 @@ int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.srs_ind = *ind; + if (ind->number_of_pdus > 0) gNB->UL_INFO.srs_ind.pdu_list = malloc(sizeof(nfapi_nr_srs_indication_pdu_t)*ind->number_of_pdus); @@ -1087,6 +1095,8 @@ int phy_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.rach_ind = *ind; + if (ind->number_of_pdus > 0) gNB->UL_INFO.rach_ind.pdu_list = malloc(sizeof(nfapi_nr_prach_indication_pdu_t)*ind->number_of_pdus); diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index de2316e4d7..e18aa7fda2 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -4126,7 +4126,7 @@ static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPa static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { - printf("ssb received and unpacked. \n"); + //printf("ssb received and unpacked. \n"); nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; return( @@ -6429,7 +6429,6 @@ static uint8_t unpack_nr_crc_indication(uint8_t **ppReadPackedMsg, uint8_t *end, return 0; } - printf("Done \n"); return 1; } diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 5c4dfa8c9f..8786e9e53c 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -935,9 +935,9 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl // save the curren time, sfn and slot pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); - // pnf_p7->sfn = sfn; + pnf_p7->sfn = sfn; - // pnf_p7->slot = slot; + pnf_p7->slot = slot; @@ -1559,26 +1559,23 @@ uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, // } // } - struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); - printf("PNF SFN:%d, PNF slot:%d, VNF SFN:%d, VNF slot:%d, SFN offset:%d, Curr time;%d.%d. \n",phy->sfn,phy->slot,sfn,slot, phy->sfn - sfn,curr_time.tv_sec,curr_time.tv_nsec); if(current_sfn_slot_dec <= recv_sfn_slot_dec + timing_window){ in_window = 1; - NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); } else if(current_sfn_slot_dec + NFAPI_MAX_SFNSLOTDEC <= recv_sfn_slot_dec + timing_window){ //checking for wrap in_window = 1; - NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); } else { - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); }//Need to add more cases - in_window = 0; // gokul + return in_window; } @@ -1848,7 +1845,7 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) { @@ -2133,7 +2130,7 @@ void pnf_handle_tx_data_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE TX_DATA_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE TX_DATA_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); #if 0 if (0 && NFAPI_SFNSF2DEC(req->sfn_sf)%100==0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX_REQ.req sfn_sf:%d pdus:%d - TX_REQ is within window\n", __FUNCTION__, @@ -3202,43 +3199,9 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) return 0; } -struct timespec pnf_timespec_add(struct timespec lhs, struct timespec rhs) -{ - struct timespec result; - - result.tv_sec = lhs.tv_sec + rhs.tv_sec; - result.tv_nsec = lhs.tv_nsec + rhs.tv_nsec; - - if(result.tv_nsec > 1e9) - { - result.tv_sec++; - result.tv_nsec-= 1e9; - } - - return result; -} - -struct timespec pnf_timespec_sub(struct timespec lhs, struct timespec rhs) -{ - struct timespec result; - if ((lhs.tv_nsec-rhs.tv_nsec)<0) - { - result.tv_sec = lhs.tv_sec-rhs.tv_sec-1; - result.tv_nsec = 1000000000+lhs.tv_nsec-rhs.tv_nsec; - } - else - { - result.tv_sec = lhs.tv_sec-rhs.tv_sec; - result.tv_nsec = lhs.tv_nsec-rhs.tv_nsec; - } - return result; -} - int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) { - uint16_t pnf_frame = 0; - uint8_t pnf_slot = 0; // initialize the mutex lock if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) { @@ -3311,23 +3274,6 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) } NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n"); - //Initializaing timing structures needed for slot ticking - - struct timespec slot_start; - clock_gettime(CLOCK_MONOTONIC, &slot_start); - - struct timespec pselect_start; - - struct timespec timeout; - timeout.tv_sec = 0; - timeout.tv_nsec = 500000; - - struct timespec slot_duration; - slot_duration.tv_sec = 0; - slot_duration.tv_nsec = 0.5e6; - - //Infinite loop - while(pnf_p7->terminate == 0) { fd_set rfds; @@ -3337,26 +3283,11 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) FD_ZERO(&rfds); FD_SET(pnf_p7->p7_sock, &rfds); - clock_gettime(CLOCK_MONOTONIC, &pselect_start); + struct timeval timeout; + timeout.tv_sec = 100; + timeout.tv_usec = 0; - //setting the timeout - - if((pselect_start.tv_sec > slot_start.tv_sec) || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) - { - // overran the end of the subframe we do not want to wait - timeout.tv_sec = 0; - timeout.tv_nsec = 0; - - //struct timespec overrun = pnf_timespec_sub(pselect_start, sf_start); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); - } - else - { - // still time before the end of the subframe wait - timeout = pnf_timespec_sub(slot_start, pselect_start); - } - - selectRetval = pselect(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout, NULL); + selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout); uint32_t now_hr_time = pnf_get_current_time_hr(); @@ -3366,19 +3297,7 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(selectRetval == 0) { // timeout - - //update slot start timing - slot_start = pnf_timespec_add(slot_start, slot_duration); - - //increment sfn/slot - if (pnf_slot == 19) - pnf_frame = (pnf_frame + 1) % 1024; - pnf_slot = (pnf_slot + 1) % 20; - pnf_p7->sfn = pnf_frame; - pnf_p7->slot = pnf_slot; - - struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); + continue; } else if (selectRetval == -1 && (errno == EINTR)) { @@ -3396,7 +3315,7 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) if(FD_ISSET(pnf_p7->p7_sock, &rfds)) { - pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); + pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); } } NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 443ccc3d49..11885d7c48 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -457,7 +457,7 @@ int send_mac_subframe_indications(vnf_p7_t* vnf_p7) int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, uint8_t* msg, const uint32_t len) { int sendto_result = sendto(vnf_p7->socket, msg, len, 0, (struct sockaddr*)&(p7_info->remote_addr), sizeof(p7_info->remote_addr)); - //printf("\nSending p7 message sfn=%d,slot=%d\n",vnf_p7->p7_connections->sfn,vnf_p7->p7_connections->slot); + //printf("P7 msg sent \n"); if(sendto_result != len) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno); @@ -534,7 +534,7 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); - //printf("segment %d \n", segment); + } } else @@ -551,7 +551,6 @@ int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* } p7_connection->sequence_number++; - return send_result; } else diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index d7e2fa5311..b84003ab6e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -97,7 +97,7 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // send indications to mac int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) { - uint16_t vnf_frame; uint8_t vnf_slot; + uint16_t vnf_frame; uint8_t vnf_slot; uint16_t slot_scheduled; if(config == 0) return -1; @@ -265,6 +265,21 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) } */ + if(setup_time > 10 && slot_scheduled == 0){ + + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + //printf("Scheduler called at SFN/slot %d.%d. \n",vnf_frame,vnf_slot); + slot_scheduled = 1; + } //long wraps = pselect_timeout.tv_nsec % 1e9; @@ -410,18 +425,18 @@ struct timespec current_time; clock_gettime(CLOCK_MONOTONIC, ¤t_time); // pselect timed out - if(setup_time > 10){ - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; + // if(setup_time > 10){ + // // Call the scheduler + // struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + // pthread_mutex_lock(&gNB->UL_INFO_mutex); + // gNB->UL_INFO.frame = vnf_frame; + // gNB->UL_INFO.slot = vnf_slot; - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); - } + // gNB->UL_INFO.module_id = gNB->Mod_id; + // gNB->UL_INFO.CC_id = gNB->CC_id; + // gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + // pthread_mutex_unlock(&gNB->UL_INFO_mutex); + // } while(curr != 0) { @@ -437,7 +452,7 @@ struct timespec current_time; { curr->slot++; } - printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); + //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); vnf_frame = curr->sfn; vnf_slot = curr->slot; struct timespec curr_time; @@ -450,17 +465,14 @@ struct timespec current_time; curr = curr->next; } send_mac_slot_indications(vnf_p7); - + slot_scheduled = 0; } else if(selectRetval > 0) { // have a p7 message if(FD_ISSET(vnf_p7->socket, &rfds)) { - printf("P7 message received \n"); - vnf_nr_p7_read_dispatch_message(vnf_p7); - - + vnf_nr_p7_read_dispatch_message(vnf_p7); } } else @@ -902,7 +914,6 @@ int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_reque { if(config == 0 || req == 0) return -1; - vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index c562dfaa41..c04bb308e2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -211,8 +211,8 @@ int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) { for (i=0; ipdcch_pdu[i].frame,gNB->pdcch_pdu[i].slot,first_free_index); if ((gNB->pdcch_pdu[i].frame == frame) && - (gNB->pdcch_pdu[i].slot==slot)) return i; - else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i; + (gNB->pdcch_pdu[i].slot==slot)) {return i;} + else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) {first_free_index=i;} } if (type == SEARCH_EXIST) return -1; @@ -227,7 +227,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15; NR_gNB_DLSCH_t *dlsch; - + //printf("find pdcch from nr_fill_dci \n"); int pdcch_id = find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST_OR_FREE); AssertFatal(pdcch_id>=0 && pdcch_idpdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); @@ -285,7 +285,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu) { nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - + //printf("find ul dci from fill_ul_dci \n"); int pdcch_id = find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST_OR_FREE); AssertFatal(pdcch_id>=0 && pdcch_idul_pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index d0359a3fa1..eeaf993c61 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -88,8 +88,8 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - if (NFAPI_MODE == NFAPI_MODE_PNF) - gNB->pucch[0]->active = 0; + // if (NFAPI_MODE == NFAPI_MODE_PNF) + // gNB->pucch[0]->active = 0; int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idnumDlDci:%d\n",frame,slot, slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); + LOG_D(PHY,"Frame %d, Slot %d: DCI processing - pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure // gNB->pdcch_pdu = pdcch_pdu; @@ -119,7 +119,7 @@ void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu) { - LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); + LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure // gNB->ul_dci_pdu = ul_dci_request_pdu; @@ -236,8 +236,10 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ } } + //printf("Inside NR schedule response SFN/slot %d.%d. \n",frame,slot); if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) - { + { + //printf("SFN/slot %d.%d Sending ul tti req \n",frame,slot); oai_nfapi_ul_tti_req(UL_tti_req); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 76b35b6378..c410805560 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -147,16 +147,16 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1); - if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { + for (int i=0; iLmax; i++) { if (gNB->ssb[i].active) { nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[i].ssb_pdu); gNB->ssb[i].active = false; } } - } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0); - + //printf("find pdcch from TX func \n"); int pdcch_pdu_id=find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST); int ul_pdcch_pdu_id=find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST); @@ -556,6 +556,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { for (int i=0;ipucch[i]; if (pucch) { + LOG_D(PHY, "SFN/slot = %d.%d, pucch[%d]->active = %d \n", frame_rx, slot_rx, i,pucch->active); if ((pucch->active == 1) && (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { @@ -585,7 +586,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; + //printf("SFN/slot %d.%d pucch active of index %d set to 0. \n", frame_rx, slot_rx, i); pucch->active = 0; + //printf("Decode pucch num ucis +=1 in %d.%d \n",frame_rx,slot_rx); break; case 2: num_ucis = gNB->UL_INFO.uci_ind.num_ucis; @@ -602,6 +605,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; + //printf("SFN/slot %d.%d pucch active of index %d set to 0. \n", frame_rx, slot_rx, i); pucch->active = 0; break; default: diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 93a2d87345..fde53c3d0c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -60,7 +60,7 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t)); future_ul_tti_req->n_pdus += 1; - LOG_I(MAC, + LOG_D(MAC, "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d on res %d\n", frame, slot, @@ -144,7 +144,7 @@ void nr_schedule_pucch(int Mod_idP, || frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) continue; - LOG_I(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); + LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %d in %d.%d O_ack %d\n",i,UE_id,curr_pucch->frame,curr_pucch->ul_slot,O_ack); nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id); memset(curr_pucch, 0, sizeof(*curr_pucch)); } @@ -983,6 +983,7 @@ static NR_UE_harq_t *find_harq(module_id_t mod_id, frame_t frame, sub_frame_t sl harq->feedback_slot, frame, slot); + //printf("handling harq \n"); remove_front_nr_list(&sched_ctrl->feedback_dl_harq); handle_dl_harq(mod_id, UE_id, pid, 0); pid = sched_ctrl->feedback_dl_harq.head; @@ -1022,12 +1023,14 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; + //printf("handle uci 0_1 find harq SFN/slot %d.%d \n",frame,slot); NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); if (!harq) break; DevAssert(harq->is_waiting); const int8_t pid = sched_ctrl->feedback_dl_harq.head; remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + //printf("handling harq \n"); handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index a3ab18735e..3ec7facbfb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1330,8 +1330,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) if (harq_id < 0) { /* PP has not selected a specific HARQ Process, get a new one */ harq_id = sched_ctrl->available_ul_harq.head; - // if(NFAPI_MODE == NFAPI_MODE_VNF) - // harq_id = 1; + //printf("SFN/slot %d.%d harq id = %d \n", frame, slot, harq_id); AssertFatal(harq_id >= 0, "no free HARQ process available for UE %d\n", UE_id); @@ -1351,8 +1350,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); cur_harq->feedback_slot = sched_pusch->slot; cur_harq->is_waiting = true; - // if (NFAPI_MODE == NFAPI_MODE_VNF) - // cur_harq->is_waiting = 0; int rnti_types[2] = { NR_RNTI_C, 0 }; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index edc3a7909b..f90361f564 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -88,7 +88,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->uci_ind.num_ucis>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + LOG_I(PHY,"PNF Sending UL_info->num_ucis:%d PDU_type: %d, SFN/SF:%d.%d \n", UL_info->uci_ind.num_ucis, UL_info->uci_ind.uci_list[0].pdu_type ,UL_info->frame, UL_info->slot); oai_nfapi_nr_uci_indication(&UL_info->uci_ind); UL_info->uci_ind.num_ucis = 0; } @@ -99,7 +99,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) const sub_frame_t slot = UL_info->slot; int num_ucis = UL_info->uci_ind.num_ucis; nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; - + //printf("handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); for (int i = 0; i < num_ucis; i++) { switch (uci_list[i].pdu_type) { case NFAPI_NR_UCI_PUSCH_PDU_TYPE: @@ -107,12 +107,14 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) break; case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + //printf("handle uci format 0_1 \n"); const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + //printf("handle uci format 2_3_4 \n"); const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); break; From d4a746ac112202eddbdf3d30c5fbe19cee2554b7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 27 Jul 2021 16:07:05 +0200 Subject: [PATCH 113/185] fix for 2 layers dlsim using layers in NR_pdsch_semi_static_t --- openair1/SIMULATION/NR_PHY/dlsim.c | 5 +-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 18 +++++------ .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 4 +-- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 32 ++++++++++++++++++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 ++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 5 ++- 6 files changed, 49 insertions(+), 17 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b597425ddf..3e80e78b35 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -263,6 +263,8 @@ void nr_dlsim_preprocessor(module_id_t module_id, NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + ps->nrOfLayers = g_nrOfLayers; + nr_set_pdsch_semi_static(scc, UE_info->CellGroup[0], sched_ctrl->active_bwp, @@ -278,7 +280,6 @@ void nr_dlsim_preprocessor(module_id_t module_id, * configuration */ ps->mcsTableIdx = g_mcsTableIdx; - sched_pdsch->nrOfLayers = g_nrOfLayers; sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm, @@ -288,7 +289,7 @@ void nr_dlsim_preprocessor(module_id_t module_id, ps->N_PRB_DMRS * ps->N_DMRS_SLOT, 0 /* N_PRB_oh, 0 for initialBWP */, 0 /* tb_scaling */, - sched_pdsch->nrOfLayers) + ps->nrOfLayers) >> 3; /* the simulator assumes the HARQ PID is equal to the slot number */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index bfdb1a01e3..5d70542377 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -603,7 +603,7 @@ void pf_dl(module_id_t module_id, /* Calculate coeff */ sched_pdsch->mcs = 9; - sched_pdsch->nrOfLayers = 1; + ps->nrOfLayers = 1; uint32_t tbs = pf_tbs[ps->mcsTableIdx][sched_pdsch->mcs]; coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id]; LOG_D(NR_MAC,"b %d, thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n", @@ -820,17 +820,17 @@ void nr_schedule_ue_spec(module_id_t module_id, const rnti_t rnti = UE_info->rnti[UE_id]; - /* POST processing */ - const uint8_t nrOfLayers = sched_pdsch->nrOfLayers; - const uint16_t R = sched_pdsch->R; - const uint8_t Qm = sched_pdsch->Qm; - const uint32_t TBS = sched_pdsch->tb_size; - /* pre-computed PDSCH values that only change if time domain * allocation/DMRS parameters change. Updated in the preprocessor through * nr_set_pdsch_semi_static() */ NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + /* POST processing */ + const uint8_t nrOfLayers = ps->nrOfLayers; + const uint16_t R = sched_pdsch->R; + const uint8_t Qm = sched_pdsch->Qm; + const uint32_t TBS = sched_pdsch->tb_size; + int8_t current_harq_pid = sched_pdsch->dl_harq_pid; if (current_harq_pid < 0) { /* PP has not selected a specific HARQ Process, get a new one */ @@ -940,7 +940,7 @@ void nr_schedule_ue_spec(module_id_t module_id, pdsch_pdu->dlDmrsScramblingId = *scc->physCellId; pdsch_pdu->SCID = 0; pdsch_pdu->numDmrsCdmGrpsNoData = ps->numDmrsCdmGrpsNoData; - pdsch_pdu->dmrsPorts = 1; + pdsch_pdu->dmrsPorts = (1<resourceAlloc = 1; @@ -1022,7 +1022,7 @@ void nr_schedule_ue_spec(module_id_t module_id, dci_payload.tpc = sched_ctrl->tpc1; // TPC for PUCCH: table 7.2.1-1 in 38.213 dci_payload.pucch_resource_indicator = pucch->resource_indicator; dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch->timing_indicator; // PDSCH to HARQ TI - dci_payload.antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 + dci_payload.antenna_ports.val = ps->dmrs_ports_id; dci_payload.dmrs_sequence_initialization.val = pdsch_pdu->SCID; LOG_D(NR_MAC, "%4d.%2d DCI type 1 payload: freq_alloc %d (%d,%d,%d), " diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 47ccc74612..e92178f9c0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -373,7 +373,7 @@ void nr_preprocessor_phytest(module_id_t module_id, nr_set_pdsch_semi_static( scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps); - sched_pdsch->nrOfLayers = target_dl_Nl; + ps->nrOfLayers = target_dl_Nl; sched_pdsch->mcs = target_dl_mcs; sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); @@ -384,7 +384,7 @@ void nr_preprocessor_phytest(module_id_t module_id, ps->N_PRB_DMRS * ps->N_DMRS_SLOT, 0 /* N_PRB_oh, 0 for initialBWP */, 0 /* tb_scaling */, - sched_pdsch->nrOfLayers) + ps->nrOfLayers) >> 3; /* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 546602427a..aeef9f6cfc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -122,6 +122,36 @@ static inline uint8_t get_max_cces(uint8_t scs) { return (nr_max_number_of_cces_per_slot[scs]); } +void set_dl_dmrs_ports(NR_pdsch_semi_static_t *ps) { + + //TODO first basic implementation of dmrs port selection + // only vaild for a single codeword + // for now it assumes a selection of Nl consecutive dmrs ports + // and a single front loaded symbol + // dmrs_ports_id is the index of Tables 7.3.1.2.2-1/2/3/4 + + switch (ps->nrOfLayers) { + case 1: + ps->dmrs_ports_id = 0; + ps->numDmrsCdmGrpsNoData = 1; + break; + case 2: + ps->dmrs_ports_id = 2; + ps->numDmrsCdmGrpsNoData = 1; + break; + case 3: + ps->dmrs_ports_id = 9; + ps->numDmrsCdmGrpsNoData = 2; + break; + case 4: + ps->dmrs_ports_id = 10; + ps->numDmrsCdmGrpsNoData = 2; + break; + default: + AssertFatal(1==0,"Number of layers %d\n not supported or not valid\n",ps->nrOfLayers); + } +} + NR_ControlResourceSet_t *get_coreset(NR_ServingCellConfigCommon_t *scc, NR_BWP_Downlink_t *bwp, NR_SearchSpace_t *ss, @@ -295,7 +325,7 @@ void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc, } else ps->mcsTableIdx = 0; - ps->numDmrsCdmGrpsNoData = num_dmrs_cdm_grps_no_data; + set_dl_dmrs_ports(ps); ps->dmrsConfigType = bwp!=NULL ? (bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1) : 0; // if no data in dmrs cdm group is 1 only even REs have no data diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index c7e6f9c5fc..756f5168dc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -415,6 +415,8 @@ int16_t ssb_index_from_prach(module_id_t module_idP, void find_SSB_and_RO_available(module_id_t module_idP); +void set_dl_dmrs_ports(NR_pdsch_semi_static_t *ps); + void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp); void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index bd88c39306..310686693b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -365,9 +365,9 @@ typedef struct NR_pdsch_semi_static { int startSymbolIndex; int nrOfSymbols; - + uint8_t nrOfLayers; uint8_t mcsTableIdx; - + uint8_t dmrs_ports_id; uint8_t N_PRB_DMRS; uint8_t N_DMRS_SLOT; uint16_t dl_dmrs_symb_pos; @@ -383,7 +383,6 @@ typedef struct NR_sched_pdsch { uint8_t mcs; /// TBS-related info - uint8_t nrOfLayers; uint16_t R; uint8_t Qm; uint32_t tb_size; From b88cc798cd843f9a8ff5bb2d7e6c804b9b3d8e6f Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 27 Jul 2021 17:52:58 +0200 Subject: [PATCH 114/185] fix for phytest --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index e92178f9c0..fc00334f41 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -368,12 +368,11 @@ void nr_preprocessor_phytest(module_id_t module_id, sched_pdsch->rbStart = rbStart; sched_pdsch->rbSize = rbSize; const int tda = sched_ctrl->active_bwp ? RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot] : 1; - const uint8_t num_dmrs_cdm_grps_no_data = 1; + ps->nrOfLayers = target_dl_Nl; if (ps->time_domain_allocation != tda || ps->numDmrsCdmGrpsNoData != num_dmrs_cdm_grps_no_data) nr_set_pdsch_semi_static( scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps); - ps->nrOfLayers = target_dl_Nl; sched_pdsch->mcs = target_dl_mcs; sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); From c1ba654a9b7ac796dd62daf8843d3830bfa4714c Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 27 Jul 2021 17:53:46 +0200 Subject: [PATCH 115/185] fix for phytest --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index fc00334f41..332c3a7afa 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -368,11 +368,13 @@ void nr_preprocessor_phytest(module_id_t module_id, sched_pdsch->rbStart = rbStart; sched_pdsch->rbSize = rbSize; const int tda = sched_ctrl->active_bwp ? RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot] : 1; + const uint8_t num_dmrs_cdm_grps_no_data = 1; ps->nrOfLayers = target_dl_Nl; if (ps->time_domain_allocation != tda || ps->numDmrsCdmGrpsNoData != num_dmrs_cdm_grps_no_data) nr_set_pdsch_semi_static( scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps); + sched_pdsch->mcs = target_dl_mcs; sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); From 5e3e4714d690480a5bf4658ca535ea978ebc72fc Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 28 Jul 2021 09:45:31 +0200 Subject: [PATCH 116/185] tentative fix for rlc initialization --- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 76f764ec37..7b9e1173d4 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -59,6 +59,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { if (rrc_inst && rrc_inst->scell_group_config) { nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,rrc_inst->scell_group_config); + AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); // if (IS_SOFTMODEM_NOS1){ //if (1) { From 13d30c96b3e881ca7ad5d3550a37ddfc757853b1 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 29 Jul 2021 07:46:16 +0200 Subject: [PATCH 117/185] temporary fix for pucch tx amp --- executables/nr-uesoftmodem.c | 1 - openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 19 ++++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 8efc9331b7..19e1bcf7b5 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -320,7 +320,6 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->rf_map.card = card_offset; UE->rf_map.chain = CC_id + chain_offset; - LOG_I(PHY,"Set UE mode %d, UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n", UE->mode, UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction); diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 61042ce5fc..6e5e624e36 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -837,9 +837,9 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ /* Generate PUCCH signal according to its format and parameters */ ue->generate_ul_signal[gNB_id] = 1; - int16_t pucch_tx_power = get_pucch_tx_power_ue( ue, gNB_id, proc, format, - nb_of_prbs, N_sc_ctrl_RB, nb_symbols, N_UCI, O_SR, O_CSI, O_ACK, - O_CRC, n_HARQ_ACK); + int16_t pucch_tx_power = get_pucch_tx_power_ue(ue, gNB_id, proc, format, + nb_of_prbs, N_sc_ctrl_RB, nb_symbols, N_UCI, O_SR, O_CSI, O_ACK, + O_CRC, n_HARQ_ACK); /* set tx power */ ue->tx_power_dBm[nr_slot_tx] = pucch_tx_power; @@ -847,15 +847,12 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ int tx_amp; -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - tx_amp = nr_get_tx_amp(pucch_tx_power, - ue->tx_power_max_dBm, - ue->frame_parms.N_RB_UL, - nb_of_prbs); -#else - tx_amp = AMP; -#endif + ue->tx_power_max_dBm, + ue->frame_parms.N_RB_UL, + nb_of_prbs); + if (tx_amp == 0) + tx_amp = AMP; switch(format) { case pucch_format0_nr: From c7106ed315c4b5828f8d79f6cdc95e29db330465 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Thu, 29 Jul 2021 11:52:50 +0000 Subject: [PATCH 118/185] tentatively adding pdcp layer init --- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 7b9e1173d4..efc46bb569 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -60,6 +60,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,rrc_inst->scell_group_config); AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); + nr_pdcp_layer_init(); // if (IS_SOFTMODEM_NOS1){ //if (1) { From 0904d32e2c663bef6623eaa8c01bdafae89623a2 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 30 Jul 2021 08:22:05 +0200 Subject: [PATCH 119/185] Revert "tentatively adding pdcp layer init" This reverts commit c7106ed315c4b5828f8d79f6cdc95e29db330465. --- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index efc46bb569..7b9e1173d4 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -60,7 +60,6 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,rrc_inst->scell_group_config); AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); - nr_pdcp_layer_init(); // if (IS_SOFTMODEM_NOS1){ //if (1) { From 8bb80c9ef0ef5c0f8b1538ce0b590c58dcca66c0 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 30 Jul 2021 12:18:14 +0200 Subject: [PATCH 120/185] another attempt to fix ping and iper issues by calling commented functions --- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 7b9e1173d4..024896b28d 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -60,13 +60,8 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,rrc_inst->scell_group_config); AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); - - // if (IS_SOFTMODEM_NOS1){ - //if (1) { - // AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); - // nr_pdcp_layer_init(); - //nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); - //} + pdcp_layer_init(); + nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); // Allocate memory for ul_config_request in the mac instance. This is now a pointer and will // point to a list of structures (one for each UL slot) to store PUSCH scheduling parameters From 2380646da0b529ce473b61a576ee6b91f4f91e0d Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Fri, 16 Jul 2021 13:00:19 +0200 Subject: [PATCH 121/185] Updated ASN to Spec 38.331 version 16.4.1 --- cmake_targets/CMakeLists.txt | 4 +- .../asn1c/ASN1_files/nr-rrc-16.4.1.asn1 | 14304 ++++++++++++++++ 2 files changed, 14306 insertions(+), 2 deletions(-) create mode 100644 openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1 diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index e7c2cbc6cd..2f94edd12b 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -474,8 +474,8 @@ include_directories ("${RRC_FULL_DIR}") #NR RRC ####### set (NR_RRC_ASN1_VERSION "NR_Rel16" ) -make_version(NR_RRC_VERSION 16 1 0) -set (NR_RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.1.0.asn1) +make_version(NR_RRC_VERSION 16 4 1) +set (NR_RRC_GRAMMAR ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1) add_definitions(-DNR_RRC_VERSION=${NR_RRC_VERSION}) set (NR_RRC_FULL_DIR ${asn1_generated_dir}/RRC_${NR_RRC_ASN1_VERSION}) diff --git a/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1 b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1 new file mode 100644 index 0000000000..80112fa2ff --- /dev/null +++ b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/nr-rrc-16.4.1.asn1 @@ -0,0 +1,14304 @@ +NR-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +-- TAG-BCCH-BCH-MESSAGE-START + +BCCH-BCH-Message ::= SEQUENCE { + message BCCH-BCH-MessageType +} + +BCCH-BCH-MessageType ::= CHOICE { + mib MIB, + messageClassExtension SEQUENCE {} +} + +-- TAG-BCCH-BCH-MESSAGE-STOP +-- TAG-BCCH-DL-SCH-MESSAGE-START + +BCCH-DL-SCH-Message ::= SEQUENCE { + message BCCH-DL-SCH-MessageType +} + +BCCH-DL-SCH-MessageType ::= CHOICE { + c1 CHOICE { + systemInformation SystemInformation, + systemInformationBlockType1 SIB1 + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-BCCH-DL-SCH-MESSAGE-STOP +-- TAG-DL-CCCH-MESSAGE-START + +DL-CCCH-Message ::= SEQUENCE { + message DL-CCCH-MessageType +} + +DL-CCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcReject RRCReject, + rrcSetup RRCSetup, + spare2 NULL, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-DL-CCCH-MESSAGE-STOP +-- TAG-DL-DCCH-MESSAGE-START + +DL-DCCH-Message ::= SEQUENCE { + message DL-DCCH-MessageType +} + +DL-DCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcReconfiguration RRCReconfiguration, + rrcResume RRCResume, + rrcRelease RRCRelease, + rrcReestablishment RRCReestablishment, + securityModeCommand SecurityModeCommand, + dlInformationTransfer DLInformationTransfer, + ueCapabilityEnquiry UECapabilityEnquiry, + counterCheck CounterCheck, + mobilityFromNRCommand MobilityFromNRCommand, + dlDedicatedMessageSegment-r16 DLDedicatedMessageSegment-r16, + ueInformationRequest-r16 UEInformationRequest-r16, + dlInformationTransferMRDC-r16 DLInformationTransferMRDC-r16, + loggedMeasurementConfiguration-r16 LoggedMeasurementConfiguration-r16, + spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-DL-DCCH-MESSAGE-STOP +-- TAG-PCCH-PCH-MESSAGE-START + +PCCH-Message ::= SEQUENCE { + message PCCH-MessageType +} + +PCCH-MessageType ::= CHOICE { + c1 CHOICE { + paging Paging, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-PCCH-PCH-MESSAGE-STOP +-- TAG-UL-CCCH-MESSAGE-START + + +UL-CCCH-Message ::= SEQUENCE { + message UL-CCCH-MessageType +} + +UL-CCCH-MessageType ::= CHOICE { + c1 CHOICE { + rrcSetupRequest RRCSetupRequest, + rrcResumeRequest RRCResumeRequest, + rrcReestablishmentRequest RRCReestablishmentRequest, + rrcSystemInfoRequest RRCSystemInfoRequest + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-UL-CCCH-MESSAGE-STOP +-- TAG-UL-CCCH1-MESSAGE-START + + +UL-CCCH1-Message ::= SEQUENCE { + message UL-CCCH1-MessageType +} + +UL-CCCH1-MessageType ::= CHOICE { + c1 CHOICE { + rrcResumeRequest1 RRCResumeRequest1, + spare3 NULL, + spare2 NULL, + spare1 NULL + + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-UL-CCCH1-MESSAGE-STOP +-- TAG-UL-DCCH-MESSAGE-START + +UL-DCCH-Message ::= SEQUENCE { + message UL-DCCH-MessageType +} + +UL-DCCH-MessageType ::= CHOICE { + c1 CHOICE { + measurementReport MeasurementReport, + rrcReconfigurationComplete RRCReconfigurationComplete, + rrcSetupComplete RRCSetupComplete, + rrcReestablishmentComplete RRCReestablishmentComplete, + rrcResumeComplete RRCResumeComplete, + securityModeComplete SecurityModeComplete, + securityModeFailure SecurityModeFailure, + ulInformationTransfer ULInformationTransfer, + locationMeasurementIndication LocationMeasurementIndication, + ueCapabilityInformation UECapabilityInformation, + counterCheckResponse CounterCheckResponse, + ueAssistanceInformation UEAssistanceInformation, + failureInformation FailureInformation, + ulInformationTransferMRDC ULInformationTransferMRDC, + scgFailureInformation SCGFailureInformation, + scgFailureInformationEUTRA SCGFailureInformationEUTRA + }, + messageClassExtension CHOICE { + c2 CHOICE { + ulDedicatedMessageSegment-r16 ULDedicatedMessageSegment-r16, + dedicatedSIBRequest-r16 DedicatedSIBRequest-r16, + mcgFailureInformation-r16 MCGFailureInformation-r16, + ueInformationResponse-r16 UEInformationResponse-r16, + sidelinkUEInformationNR-r16 SidelinkUEInformationNR-r16, + ulInformationTransferIRAT-r16 ULInformationTransferIRAT-r16, + iabOtherInformation-r16 IABOtherInformation-r16, + spare9 NULL, spare8 NULL, spare7 NULL, spare6 NULL, + spare5 NULL, spare4 NULL, spare3 NULL, spare2 NULL, spare1 NULL + }, + messageClassExtensionFuture-r16 SEQUENCE {} + } +} + +-- TAG-UL-DCCH-MESSAGE-STOP +-- TAG-COUNTERCHECK-START + + +CounterCheck ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + counterCheck CounterCheck-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CounterCheck-IEs ::= SEQUENCE { + drb-CountMSB-InfoList DRB-CountMSB-InfoList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +DRB-CountMSB-InfoList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-CountMSB-Info + +DRB-CountMSB-Info ::= SEQUENCE { + drb-Identity DRB-Identity, + countMSB-Uplink INTEGER(0..33554431), + countMSB-Downlink INTEGER(0..33554431) +} + +-- TAG-COUNTERCHECK-STOP +-- TAG-COUNTERCHECKRESPONSE-START + +CounterCheckResponse ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + counterCheckResponse CounterCheckResponse-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +CounterCheckResponse-IEs ::= SEQUENCE { + drb-CountInfoList DRB-CountInfoList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL + +} + +DRB-CountInfoList ::= SEQUENCE (SIZE (0..maxDRB)) OF DRB-CountInfo + +DRB-CountInfo ::= SEQUENCE { + drb-Identity DRB-Identity, + count-Uplink INTEGER(0..4294967295), + count-Downlink INTEGER(0..4294967295) +} + +-- TAG-COUNTERCHECKRESPONSE-STOP +-- TAG-DEDICATEDSIBREQUEST-START + +DedicatedSIBRequest-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + dedicatedSIBRequest-r16 DedicatedSIBRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DedicatedSIBRequest-r16-IEs ::= SEQUENCE { + onDemandSIB-RequestList-r16 SEQUENCE { + + requestedSIB-List-r16 SEQUENCE (SIZE (1..maxOnDemandSIB-r16)) OF SIB-ReqInfo-r16 OPTIONAL, + requestedPosSIB-List-r16 SEQUENCE (SIZE (1..maxOnDemandPosSIB-r16)) OF PosSIB-ReqInfo-r16 OPTIONAL + } OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SIB-ReqInfo-r16 ::= ENUMERATED { sib12, sib13, sib14, spare5, spare4, spare3, spare2, spare1 } + +PosSIB-ReqInfo-r16 ::= SEQUENCE { + gnss-id-r16 GNSS-ID-r16 OPTIONAL, + sbas-id-r16 SBAS-ID-r16 OPTIONAL, + posSibType-r16 ENUMERATED { posSibType1-1, posSibType1-2, posSibType1-3, posSibType1-4, posSibType1-5, posSibType1-6, + posSibType1-7, posSibType1-8, posSibType2-1, posSibType2-2, posSibType2-3, posSibType2-4, + posSibType2-5, posSibType2-6, posSibType2-7, posSibType2-8, posSibType2-9, posSibType2-10, + posSibType2-11, posSibType2-12, posSibType2-13, posSibType2-14, posSibType2-15, + posSibType2-16, posSibType2-17, posSibType2-18, posSibType2-19, posSibType2-20, + posSibType2-21, posSibType2-22, posSibType2-23, posSibType3-1, posSibType4-1, + posSibType5-1, posSibType6-1, posSibType6-2, posSibType6-3,... } +} + +-- TAG-DEDICATEDSIBREQUEST-STOP +-- TAG-DLDEDICATEDMESSAGESEGMENT-START + + +DLDedicatedMessageSegment-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + dlDedicatedMessageSegment-r16 DLDedicatedMessageSegment-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLDedicatedMessageSegment-r16-IEs ::= SEQUENCE { + segmentNumber-r16 INTEGER(0..4), + rrc-MessageSegmentContainer-r16 OCTET STRING, + rrc-MessageSegmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLDEDICATEDMESSAGESEGMENT-STOP +-- TAG-DLINFORMATIONTRANSFER-START + +DLInformationTransfer ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + dlInformationTransfer DLInformationTransfer-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLInformationTransfer-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension DLInformationTransfer-v1610-IEs OPTIONAL +} + +DLInformationTransfer-v1610-IEs ::= SEQUENCE { + referenceTimeInfo-r16 ReferenceTimeInfo-r16 OPTIONAL, -- Need R + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLINFORMATIONTRANSFER-STOP +-- TAG-DLINFORMATIONTRANSFERMRDC-START + +DLInformationTransferMRDC-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + dlInformationTransferMRDC-r16 DLInformationTransferMRDC-r16-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +DLInformationTransferMRDC-r16-IEs::= SEQUENCE { + dl-DCCH-MessageNR-r16 OCTET STRING OPTIONAL, -- Need N + dl-DCCH-MessageEUTRA-r16 OCTET STRING OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-DLINFORMATIONTRANSFERMRDC-STOP +-- TAG-FAILUREINFORMATION-START + +FailureInformation ::= SEQUENCE { + criticalExtensions CHOICE { + failureInformation FailureInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +FailureInformation-IEs ::= SEQUENCE { + failureInfoRLC-Bearer FailureInfoRLC-Bearer OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension FailureInformation-v1610-IEs OPTIONAL +} + +FailureInfoRLC-Bearer ::= SEQUENCE { + cellGroupId CellGroupId, + logicalChannelIdentity LogicalChannelIdentity, + failureType ENUMERATED {rlc-failure, spare3, spare2, spare1} +} + +FailureInformation-v1610-IEs ::= SEQUENCE { + failureInfoDAPS-r16 FailureInfoDAPS-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureInfoDAPS-r16 ::= SEQUENCE { + failureType-r16 ENUMERATED {daps-failure, spare3, spare2, spare1} +} + +-- TAG-FAILUREINFORMATION-STOP +-- TAG-IABOTHERINFORMATION-START + +IABOtherInformation-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + iabOtherInformation-r16 IABOtherInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +IABOtherInformation-r16-IEs ::= SEQUENCE { + ip-InfoType-r16 CHOICE { + iab-IP-Request-r16 SEQUENCE { + iab-IPv4-AddressNumReq-r16 IAB-IP-AddressNumReq-r16 OPTIONAL, + iab-IPv6-AddressReq-r16 CHOICE { + iab-IPv6-AddressNumReq-r16 IAB-IP-AddressNumReq-r16, + iab-IPv6-AddressPrefixReq-r16 IAB-IP-AddressPrefixReq-r16, + ... + } OPTIONAL + }, + iab-IP-Report-r16 SEQUENCE { + iab-IPv4-AddressReport-r16 IAB-IP-AddressAndTraffic-r16 OPTIONAL, + iab-IPv6-Report-r16 CHOICE { + iab-IPv6-AddressReport-r16 IAB-IP-AddressAndTraffic-r16, + iab-IPv6-PrefixReport-r16 IAB-IP-PrefixAndTraffic-r16, + ... + } OPTIONAL + }, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +IAB-IP-AddressNumReq-r16 ::= SEQUENCE { + all-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + f1-C-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + f1-U-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + non-F1-Traffic-NumReq-r16 INTEGER (1..8) OPTIONAL, + ... +} + +IAB-IP-AddressPrefixReq-r16 ::= SEQUENCE { + all-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + f1-C-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + f1-U-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + non-F1-Traffic-PrefixReq-r16 ENUMERATED {true} OPTIONAL, + ... +} + +IAB-IP-AddressAndTraffic-r16 ::= SEQUENCE { + all-Traffic-IAB-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + f1-C-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + f1-U-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL, + non-F1-Traffic-IP-Address-r16 SEQUENCE (SIZE(1..8)) OF IAB-IP-Address-r16 OPTIONAL +} + +IAB-IP-PrefixAndTraffic-r16 ::= SEQUENCE { + all-Traffic-IAB-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + f1-C-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + f1-U-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, + non-F1-Traffic-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL +} + +-- TAG-IABOTHERINFORMATION-STOP +-- TAG-LOCATIONMEASUREMENTINDICATION-START + +LocationMeasurementIndication ::= SEQUENCE { + criticalExtensions CHOICE { + locationMeasurementIndication LocationMeasurementIndication-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +LocationMeasurementIndication-IEs ::= SEQUENCE { + measurementIndication SetupRelease {LocationMeasurementInfo}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-LOCATIONMEASUREMENTINDICATION-STOP +-- TAG-LOGGEDMEASUREMENTCONFIGURATION-START + +LoggedMeasurementConfiguration-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + loggedMeasurementConfiguration-r16 LoggedMeasurementConfiguration-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +LoggedMeasurementConfiguration-r16-IEs ::= SEQUENCE { + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + absoluteTimeInfo-r16 AbsoluteTimeInfo-r16, + areaConfiguration-r16 AreaConfiguration-r16 OPTIONAL, --Need R + plmn-IdentityList-r16 PLMN-IdentityList2-r16 OPTIONAL, --Need R + bt-NameList-r16 SetupRelease {BT-NameList-r16} OPTIONAL, --Need M + wlan-NameList-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, --Need M + sensor-NameList-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, --Need M + loggingDuration-r16 LoggingDuration-r16, + reportType CHOICE { + periodical LoggedPeriodicalReportConfig-r16, + eventTriggered LoggedEventTriggerConfig-r16, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +LoggedPeriodicalReportConfig-r16 ::= SEQUENCE { + loggingInterval-r16 LoggingInterval-r16, + ... + } + +LoggedEventTriggerConfig-r16 ::= SEQUENCE { + eventType-r16 EventType-r16, + loggingInterval-r16 LoggingInterval-r16, + ... +} + +EventType-r16 ::= CHOICE { + outOfCoverage NULL, + eventL1 SEQUENCE { + l1-Threshold MeasTriggerQuantity, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + ... +} + +-- TAG-LOGGEDMEASUREMENTCONFIGURATION-STOP +-- TAG-MCGFAILUREINFORMATION-START + +MCGFailureInformation-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + mcgFailureInformation-r16 MCGFailureInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MCGFailureInformation-r16-IEs ::= SEQUENCE { + failureReportMCG-r16 FailureReportMCG-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportMCG-r16 ::= SEQUENCE { + failureType-r16 ENUMERATED {t310-Expiry, randomAccessProblem, rlc-MaxNumRetx, + t312-Expiry-r16, lbt-Failure-r16, beamFailureRecoveryFailure-r16, + bh-RLF-r16, spare1} OPTIONAL, + measResultFreqList-r16 MeasResultList2NR OPTIONAL, + measResultFreqListEUTRA-r16 MeasResultList2EUTRA OPTIONAL, + measResultSCG-r16 OCTET STRING (CONTAINING MeasResultSCG-Failure) OPTIONAL, + measResultSCG-EUTRA-r16 OCTET STRING OPTIONAL, + measResultFreqListUTRA-FDD-r16 MeasResultList2UTRA OPTIONAL, + ... +} + +MeasResultList2UTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2UTRA-FDD-r16 + +MeasResult2UTRA-FDD-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueUTRA-FDD-r16, + measResultNeighCellList-r16 MeasResultListUTRA-FDD-r16 +} + +MeasResultList2EUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2EUTRA-r16 + +-- TAG-MCGFAILUREINFORMATION-STOP +-- TAG-MEASUREMENTREPORT-START + +MeasurementReport ::= SEQUENCE { + criticalExtensions CHOICE { + measurementReport MeasurementReport-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementReport-IEs ::= SEQUENCE { + measResults MeasResults, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-MEASUREMENTREPORT-STOP +-- TAG-MIB-START + +MIB ::= SEQUENCE { + systemFrameNumber BIT STRING (SIZE (6)), + subCarrierSpacingCommon ENUMERATED {scs15or60, scs30or120}, + ssb-SubcarrierOffset INTEGER (0..15), + dmrs-TypeA-Position ENUMERATED {pos2, pos3}, + pdcch-ConfigSIB1 PDCCH-ConfigSIB1, + cellBarred ENUMERATED {barred, notBarred}, + intraFreqReselection ENUMERATED {allowed, notAllowed}, + spare BIT STRING (SIZE (1)) +} + +-- TAG-MIB-STOP +-- TAG-MOBILITYFROMNRCOMMAND-START + +MobilityFromNRCommand ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + mobilityFromNRCommand MobilityFromNRCommand-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +MobilityFromNRCommand-IEs ::= SEQUENCE { + targetRAT-Type ENUMERATED { eutra, utra-fdd-v1610, spare2, spare1, ...}, + targetRAT-MessageContainer OCTET STRING, + nas-SecurityParamFromNR OCTET STRING OPTIONAL, -- Cond HO-ToEPCUTRAN + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension MobilityFromNRCommand-v1610-IEs OPTIONAL +} + +MobilityFromNRCommand-v1610-IEs ::= SEQUENCE { + voiceFallbackIndication-r16 ENUMERATED {true} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-MOBILITYFROMNRCOMMAND-STOP +-- TAG-PAGING-START + +Paging ::= SEQUENCE { + pagingRecordList PagingRecordList OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +PagingRecordList ::= SEQUENCE (SIZE(1..maxNrofPageRec)) OF PagingRecord + +PagingRecord ::= SEQUENCE { + ue-Identity PagingUE-Identity, + accessType ENUMERATED {non3GPP} OPTIONAL, -- Need N + ... +} + +PagingUE-Identity ::= CHOICE { + ng-5G-S-TMSI NG-5G-S-TMSI, + fullI-RNTI I-RNTI-Value, + ... +} + +-- TAG-PAGING-STOP +-- TAG-RRCREESTABLISHMENT-START + +RRCReestablishment ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReestablishment RRCReestablishment-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReestablishment-IEs ::= SEQUENCE { + nextHopChainingCount NextHopChainingCount, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCREESTABLISHMENT-STOP +-- TAG-RRCREESTABLISHMENTCOMPLETE-START + +RRCReestablishmentComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReestablishmentComplete RRCReestablishmentComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReestablishmentComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReestablishmentComplete-v1610-IEs OPTIONAL +} + +RRCReestablishmentComplete-v1610-IEs ::= SEQUENCE { + ue-MeasurementsAvailable-r16 UE-MeasurementsAvailable-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCREESTABLISHMENTCOMPLETE-STOP +-- TAG-RRCREESTABLISHMENTREQUEST-START + + +RRCReestablishmentRequest ::= SEQUENCE { + rrcReestablishmentRequest RRCReestablishmentRequest-IEs +} + +RRCReestablishmentRequest-IEs ::= SEQUENCE { + ue-Identity ReestabUE-Identity, + reestablishmentCause ReestablishmentCause, + spare BIT STRING (SIZE (1)) +} + +ReestabUE-Identity ::= SEQUENCE { + c-RNTI RNTI-Value, + physCellId PhysCellId, + shortMAC-I ShortMAC-I +} + +ReestablishmentCause ::= ENUMERATED {reconfigurationFailure, handoverFailure, otherFailure, spare1} + +-- TAG-RRCREESTABLISHMENTREQUEST-STOP +-- TAG-RRCRECONFIGURATION-START + +RRCReconfiguration ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfiguration RRCReconfiguration-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfiguration-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig OPTIONAL, -- Need M + secondaryCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Cond SCG + measConfig MeasConfig OPTIONAL, -- Need M + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReconfiguration-v1530-IEs OPTIONAL +} + +RRCReconfiguration-v1530-IEs ::= SEQUENCE { + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Need M + fullConfig ENUMERATED {true} OPTIONAL, -- Cond FullConfig + dedicatedNAS-MessageList SEQUENCE (SIZE(1..maxDRB)) OF DedicatedNAS-Message OPTIONAL, -- Cond nonHO + masterKeyUpdate MasterKeyUpdate OPTIONAL, -- Cond MasterKeyChange + dedicatedSIB1-Delivery OCTET STRING (CONTAINING SIB1) OPTIONAL, -- Need N + dedicatedSystemInformationDelivery OCTET STRING (CONTAINING SystemInformation) OPTIONAL, -- Need N + otherConfig OtherConfig OPTIONAL, -- Need M + nonCriticalExtension RRCReconfiguration-v1540-IEs OPTIONAL +} + +RRCReconfiguration-v1540-IEs ::= SEQUENCE { + otherConfig-v1540 OtherConfig-v1540 OPTIONAL, -- Need M + nonCriticalExtension RRCReconfiguration-v1560-IEs OPTIONAL +} + +RRCReconfiguration-v1560-IEs ::= SEQUENCE { + mrdc-SecondaryCellGroupConfig SetupRelease { MRDC-SecondaryCellGroupConfig } OPTIONAL, -- Need M + radioBearerConfig2 OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, -- Need M + sk-Counter SK-Counter OPTIONAL, -- Need N + nonCriticalExtension RRCReconfiguration-v1610-IEs OPTIONAL +} +RRCReconfiguration-v1610-IEs ::= SEQUENCE { + otherConfig-v1610 OtherConfig-v1610 OPTIONAL, -- Need M + bap-Config-r16 SetupRelease { BAP-Config-r16 } OPTIONAL, -- Need M + iab-IP-AddressConfigurationList-r16 IAB-IP-AddressConfigurationList-r16 OPTIONAL, -- Need M + conditionalReconfiguration-r16 ConditionalReconfiguration-r16 OPTIONAL, -- Need M + daps-SourceRelease-r16 ENUMERATED{true} OPTIONAL, -- Need N + t316-r16 SetupRelease {T316-r16} OPTIONAL, -- Need M + needForGapsConfigNR-r16 SetupRelease {NeedForGapsConfigNR-r16} OPTIONAL, -- Need M + onDemandSIB-Request-r16 SetupRelease { OnDemandSIB-Request-r16 } OPTIONAL, -- Need M + dedicatedPosSysInfoDelivery-r16 OCTET STRING (CONTAINING PosSystemInformation-r16-IEs) OPTIONAL, -- Need N + sl-ConfigDedicatedNR-r16 SetupRelease {SL-ConfigDedicatedNR-r16} OPTIONAL, -- Need M + sl-ConfigDedicatedEUTRA-Info-r16 SetupRelease {SL-ConfigDedicatedEUTRA-Info-r16} OPTIONAL, -- Need M + targetCellSMTC-SCG-r16 SSB-MTC OPTIONAL, -- Need S + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +MRDC-SecondaryCellGroupConfig ::= SEQUENCE { + mrdc-ReleaseAndAdd ENUMERATED {true} OPTIONAL, -- Need N + mrdc-SecondaryCellGroup CHOICE { + nr-SCG OCTET STRING (CONTAINING RRCReconfiguration), + eutra-SCG OCTET STRING + } +} + +BAP-Config-r16 ::= SEQUENCE { + bap-Address-r16 BIT STRING (SIZE (10)) OPTIONAL, -- Need M + defaultUL-BAP-RoutingID-r16 BAP-RoutingID-r16 OPTIONAL, -- Need M + defaultUL-BH-RLC-Channel-r16 BH-RLC-ChannelID-r16 OPTIONAL, -- Need M + flowControlFeedbackType-r16 ENUMERATED {perBH-RLC-Channel, perRoutingID, both} OPTIONAL, -- Need R + ... +} + +MasterKeyUpdate ::= SEQUENCE { + keySetChangeIndicator BOOLEAN, + nextHopChainingCount NextHopChainingCount, + nas-Container OCTET STRING OPTIONAL, -- Cond securityNASC + ... +} + +OnDemandSIB-Request-r16 ::= SEQUENCE { + onDemandSIB-RequestProhibitTimer-r16 ENUMERATED {s0, s0dot5, s1, s2, s5, s10, s20, s30} +} + +T316-r16 ::= ENUMERATED {ms50, ms100, ms200, ms300, ms400, ms500, ms600, ms1000, ms1500, ms2000} + +IAB-IP-AddressConfigurationList-r16 ::= SEQUENCE { + iab-IP-AddressToAddModList-r16 SEQUENCE (SIZE(1..maxIAB-IP-Address-r16)) OF IAB-IP-AddressConfiguration-r16 OPTIONAL, -- Need N + iab-IP-AddressToReleaseList-r16 SEQUENCE (SIZE(1..maxIAB-IP-Address-r16)) OF IAB-IP-AddressIndex-r16 OPTIONAL, -- Need N + ... +} + +IAB-IP-AddressConfiguration-r16 ::= SEQUENCE { + iab-IP-AddressIndex-r16 IAB-IP-AddressIndex-r16, + iab-IP-Address-r16 IAB-IP-Address-r16 OPTIONAL, -- Need M + iab-IP-Usage-r16 IAB-IP-Usage-r16 OPTIONAL, -- Need M + iab-donor-DU-BAP-Address-r16 BIT STRING (SIZE(10)) OPTIONAL, -- Need M +... +} + +SL-ConfigDedicatedEUTRA-Info-r16 ::= SEQUENCE { + sl-ConfigDedicatedEUTRA-r16 OCTET STRING OPTIONAL, -- Need M + sl-TimeOffsetEUTRA-List-r16 SEQUENCE (SIZE (8)) OF SL-TimeOffsetEUTRA-r16 OPTIONAL -- Need M +} + +SL-TimeOffsetEUTRA-r16 ::= ENUMERATED {ms0, ms0dot25, ms0dot5, ms0dot625, ms0dot75, ms1, ms1dot25, ms1dot5, ms1dot75, + ms2, ms2dot5, ms3, ms4, ms5, ms6, ms8, ms10, ms20} + +-- TAG-RRCRECONFIGURATION-STOP +-- TAG-RRCRECONFIGURATIONCOMPLETE-START + +RRCReconfigurationComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationComplete RRCReconfigurationComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1530-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1530-IEs ::= SEQUENCE { + uplinkTxDirectCurrentList UplinkTxDirectCurrentList OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1560-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1560-IEs ::= SEQUENCE { + scg-Response CHOICE { + nr-SCG-Response OCTET STRING (CONTAINING RRCReconfigurationComplete), + eutra-SCG-Response OCTET STRING + } OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1610-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1610-IEs ::= SEQUENCE { + ue-MeasurementsAvailable-r16 UE-MeasurementsAvailable-r16 OPTIONAL, + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL, + nonCriticalExtension RRCReconfigurationComplete-v1640-IEs OPTIONAL +} + +RRCReconfigurationComplete-v1640-IEs ::= SEQUENCE { + uplinkTxDirectCurrentTwoCarrierList-r16 UplinkTxDirectCurrentTwoCarrierList-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRECONFIGURATIONCOMPLETE-STOP +-- TAG-RRCREJECT-START + +RRCReject ::= SEQUENCE { + criticalExtensions CHOICE { + rrcReject RRCReject-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReject-IEs ::= SEQUENCE { + waitTime RejectWaitTime OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCREJECT-STOP +-- TAG-RRCRELEASE-START + +RRCRelease ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcRelease RRCRelease-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCRelease-IEs ::= SEQUENCE { + redirectedCarrierInfo RedirectedCarrierInfo OPTIONAL, -- Need N + cellReselectionPriorities CellReselectionPriorities OPTIONAL, -- Need R + suspendConfig SuspendConfig OPTIONAL, -- Need R + deprioritisationReq SEQUENCE { + deprioritisationType ENUMERATED {frequency, nr}, + deprioritisationTimer ENUMERATED {min5, min10, min15, min30} + } OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCRelease-v1540-IEs OPTIONAL +} + +RRCRelease-v1540-IEs ::= SEQUENCE { + waitTime RejectWaitTime OPTIONAL, -- Need N + nonCriticalExtension RRCRelease-v1610-IEs OPTIONAL +} + +RRCRelease-v1610-IEs ::= SEQUENCE { + voiceFallbackIndication-r16 ENUMERATED {true} OPTIONAL, -- Need N + measIdleConfig-r16 SetupRelease {MeasIdleConfigDedicated-r16} OPTIONAL, -- Need M + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +RedirectedCarrierInfo ::= CHOICE { + nr CarrierInfoNR, + eutra RedirectedCarrierInfo-EUTRA, + ... +} + +RedirectedCarrierInfo-EUTRA ::= SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cnType ENUMERATED {epc,fiveGC} OPTIONAL -- Need N +} + +CarrierInfoNR ::= SEQUENCE { + carrierFreq ARFCN-ValueNR, + ssbSubcarrierSpacing SubcarrierSpacing, + smtc SSB-MTC OPTIONAL, -- Need S + ... +} + +SuspendConfig ::= SEQUENCE { + fullI-RNTI I-RNTI-Value, + shortI-RNTI ShortI-RNTI-Value, + ran-PagingCycle PagingCycle, + ran-NotificationAreaInfo RAN-NotificationAreaInfo OPTIONAL, -- Need M + t380 PeriodicRNAU-TimerValue OPTIONAL, -- Need R + nextHopChainingCount NextHopChainingCount, + ... +} + +PeriodicRNAU-TimerValue ::= ENUMERATED { min5, min10, min20, min30, min60, min120, min360, min720} + + +CellReselectionPriorities ::= SEQUENCE { + freqPriorityListEUTRA FreqPriorityListEUTRA OPTIONAL, -- Need M + freqPriorityListNR FreqPriorityListNR OPTIONAL, -- Need M + t320 ENUMERATED {min5, min10, min20, min30, min60, min120, min180, spare1} OPTIONAL, -- Need R + ... +} + +PagingCycle ::= ENUMERATED {rf32, rf64, rf128, rf256} + +FreqPriorityListEUTRA ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityEUTRA + +FreqPriorityListNR ::= SEQUENCE (SIZE (1..maxFreq)) OF FreqPriorityNR + +FreqPriorityEUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL -- Need R +} + +FreqPriorityNR ::= SEQUENCE { + carrierFreq ARFCN-ValueNR, + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL -- Need R +} + +RAN-NotificationAreaInfo ::= CHOICE { + cellList PLMN-RAN-AreaCellList, + ran-AreaConfigList PLMN-RAN-AreaConfigList, + ... +} + +PLMN-RAN-AreaCellList ::= SEQUENCE (SIZE (1.. maxPLMNIdentities)) OF PLMN-RAN-AreaCell + +PLMN-RAN-AreaCell ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, -- Need S + ran-AreaCells SEQUENCE (SIZE (1..32)) OF CellIdentity +} + +PLMN-RAN-AreaConfigList ::= SEQUENCE (SIZE (1..maxPLMNIdentities)) OF PLMN-RAN-AreaConfig + +PLMN-RAN-AreaConfig ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, -- Need S + ran-Area SEQUENCE (SIZE (1..16)) OF RAN-AreaConfig +} + +RAN-AreaConfig ::= SEQUENCE { + trackingAreaCode TrackingAreaCode, + ran-AreaCodeList SEQUENCE (SIZE (1..32)) OF RAN-AreaCode OPTIONAL -- Need R +} + +-- TAG-RRCRELEASE-STOP +-- TAG-RRCRESUME-START + +RRCResume ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcResume RRCResume-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCResume-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig OPTIONAL, -- Need M + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig) OPTIONAL, -- Need M + measConfig MeasConfig OPTIONAL, -- Need M + fullConfig ENUMERATED {true} OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCResume-v1560-IEs OPTIONAL +} + +RRCResume-v1560-IEs ::= SEQUENCE { + radioBearerConfig2 OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, -- Need M + sk-Counter SK-Counter OPTIONAL, -- Need N + nonCriticalExtension RRCResume-v1610-IEs OPTIONAL +} + +RRCResume-v1610-IEs ::= SEQUENCE { + idleModeMeasurementReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + restoreMCG-SCells-r16 ENUMERATED {true} OPTIONAL, -- Need N + restoreSCG-r16 ENUMERATED {true} OPTIONAL, -- Need N + mrdc-SecondaryCellGroup-r16 CHOICE { + nr-SCG-r16 OCTET STRING (CONTAINING RRCReconfiguration), + eutra-SCG-r16 OCTET STRING + } OPTIONAL, -- Cond RestoreSCG + needForGapsConfigNR-r16 SetupRelease {NeedForGapsConfigNR-r16} OPTIONAL, -- Need M + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCRESUME-STOP +-- TAG-RRCRESUMECOMPLETE-START + +RRCResumeComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcResumeComplete RRCResumeComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCResumeComplete-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, + selectedPLMN-Identity INTEGER (1..maxPLMN) OPTIONAL, + uplinkTxDirectCurrentList UplinkTxDirectCurrentList OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCResumeComplete-v1610-IEs OPTIONAL +} + +RRCResumeComplete-v1610-IEs ::= SEQUENCE { + idleMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + measResultIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL, + measResultIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + scg-Response-r16 CHOICE { + nr-SCG-Response OCTET STRING (CONTAINING RRCReconfigurationComplete), + eutra-SCG-Response OCTET STRING + } OPTIONAL, + ue-MeasurementsAvailable-r16 UE-MeasurementsAvailable-r16 OPTIONAL, + mobilityHistoryAvail-r16 ENUMERATED {true} OPTIONAL, + mobilityState-r16 ENUMERATED {normal, medium, high, spare} OPTIONAL, + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL, + nonCriticalExtension RRCResumeComplete-v1640-IEs OPTIONAL +} + +RRCResumeComplete-v1640-IEs ::= SEQUENCE { + uplinkTxDirectCurrentTwoCarrierList-r16 UplinkTxDirectCurrentTwoCarrierList-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRESUMECOMPLETE-STOP +-- TAG-RRCRESUMEREQUEST-START + +RRCResumeRequest ::= SEQUENCE { + rrcResumeRequest RRCResumeRequest-IEs +} + +RRCResumeRequest-IEs ::= SEQUENCE { + resumeIdentity ShortI-RNTI-Value, + resumeMAC-I BIT STRING (SIZE (16)), + resumeCause ResumeCause, + spare BIT STRING (SIZE (1)) +} + +-- TAG-RRCRESUMEREQUEST-STOP +-- TAG-RRCRESUMEREQUEST1-START + +RRCResumeRequest1 ::= SEQUENCE { + rrcResumeRequest1 RRCResumeRequest1-IEs +} + +RRCResumeRequest1-IEs ::= SEQUENCE { + resumeIdentity I-RNTI-Value, + resumeMAC-I BIT STRING (SIZE (16)), + resumeCause ResumeCause, + spare BIT STRING (SIZE (1)) +} + +-- TAG-RRCRESUMEREQUEST1-STOP +-- TAG-RRCSETUP-START + +RRCSetup ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcSetup RRCSetup-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCSetup-IEs ::= SEQUENCE { + radioBearerConfig RadioBearerConfig, + masterCellGroup OCTET STRING (CONTAINING CellGroupConfig), + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-RRCSETUP-STOP +-- TAG-RRCSETUPCOMPLETE-START + +RRCSetupComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcSetupComplete RRCSetupComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCSetupComplete-IEs ::= SEQUENCE { + selectedPLMN-Identity INTEGER (1..maxPLMN), + registeredAMF RegisteredAMF OPTIONAL, + guami-Type ENUMERATED {native, mapped} OPTIONAL, + s-NSSAI-List SEQUENCE (SIZE (1..maxNrofS-NSSAI)) OF S-NSSAI OPTIONAL, + dedicatedNAS-Message DedicatedNAS-Message, + ng-5G-S-TMSI-Value CHOICE { + ng-5G-S-TMSI NG-5G-S-TMSI, + ng-5G-S-TMSI-Part2 BIT STRING (SIZE (9)) + } OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension RRCSetupComplete-v1610-IEs OPTIONAL +} + +RRCSetupComplete-v1610-IEs ::= SEQUENCE { + iab-NodeIndication-r16 ENUMERATED {true} OPTIONAL, + idleMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + ue-MeasurementsAvailable-r16 UE-MeasurementsAvailable-r16 OPTIONAL, + mobilityHistoryAvail-r16 ENUMERATED {true} OPTIONAL, + mobilityState-r16 ENUMERATED {normal, medium, high, spare} OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +RegisteredAMF ::= SEQUENCE { + plmn-Identity PLMN-Identity OPTIONAL, + amf-Identifier AMF-Identifier +} + +-- TAG-RRCSETUPCOMPLETE-STOP +-- TAG-RRCSETUPREQUEST-START + +RRCSetupRequest ::= SEQUENCE { + rrcSetupRequest RRCSetupRequest-IEs +} + +RRCSetupRequest-IEs ::= SEQUENCE { + ue-Identity InitialUE-Identity, + establishmentCause EstablishmentCause, + spare BIT STRING (SIZE (1)) +} + +InitialUE-Identity ::= CHOICE { + ng-5G-S-TMSI-Part1 BIT STRING (SIZE (39)), + randomValue BIT STRING (SIZE (39)) +} + +EstablishmentCause ::= ENUMERATED { + emergency, highPriorityAccess, mt-Access, mo-Signalling, + mo-Data, mo-VoiceCall, mo-VideoCall, mo-SMS, mps-PriorityAccess, mcs-PriorityAccess, + spare6, spare5, spare4, spare3, spare2, spare1} + +-- TAG-RRCSETUPREQUEST-STOP +-- TAG-RRCSYSTEMINFOREQUEST-START + +RRCSystemInfoRequest ::= SEQUENCE { + criticalExtensions CHOICE { + rrcSystemInfoRequest RRCSystemInfoRequest-IEs, + criticalExtensionsFuture-r16 CHOICE { + rrcPosSystemInfoRequest-r16 RRC-PosSystemInfoRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } + } +} + +RRCSystemInfoRequest-IEs ::= SEQUENCE { + requested-SI-List BIT STRING (SIZE (maxSI-Message)), --32bits + spare BIT STRING (SIZE (12)) +} + +RRC-PosSystemInfoRequest-r16-IEs ::= SEQUENCE { + requestedPosSI-List BIT STRING (SIZE (maxSI-Message)), --32bits + spare BIT STRING (SIZE (11)) +} + +-- TAG-RRCSYSTEMINFOREQUEST-STOP +-- TAG-SCGFAILUREINFORMATION-START + +SCGFailureInformation ::= SEQUENCE { + criticalExtensions CHOICE { + scgFailureInformation SCGFailureInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCGFailureInformation-IEs ::= SEQUENCE { + failureReportSCG FailureReportSCG OPTIONAL, + nonCriticalExtension SCGFailureInformation-v1590-IEs OPTIONAL +} + +SCGFailureInformation-v1590-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportSCG ::= SEQUENCE { + failureType ENUMERATED { + t310-Expiry, randomAccessProblem, + rlc-MaxNumRetx, + synchReconfigFailureSCG, scg-ReconfigFailure, + srb3-IntegrityFailure, other-r16, spare1}, + measResultFreqList MeasResultFreqList OPTIONAL, + measResultSCG-Failure OCTET STRING (CONTAINING MeasResultSCG-Failure) OPTIONAL, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL, + failureType-v1610 ENUMERATED {scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, bh-RLF-r16, spare4, spare3, spare2, spare1} OPTIONAL + ]] +} + +MeasResultFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2NR + + +-- TAG-SCGFAILUREINFORMATION-STOP +-- TAG-SCGFAILUREINFORMATIONEUTRA-START + +SCGFailureInformationEUTRA ::= SEQUENCE { + criticalExtensions CHOICE { + scgFailureInformationEUTRA SCGFailureInformationEUTRA-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SCGFailureInformationEUTRA-IEs ::= SEQUENCE { + failureReportSCG-EUTRA FailureReportSCG-EUTRA OPTIONAL, + nonCriticalExtension SCGFailureInformationEUTRA-v1590-IEs OPTIONAL +} + +SCGFailureInformationEUTRA-v1590-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +FailureReportSCG-EUTRA ::= SEQUENCE { + failureType ENUMERATED { + t313-Expiry, randomAccessProblem,rlc-MaxNumRetx, + scg-ChangeFailure,scg-lbtFailure-r16, + beamFailureRecoveryFailure-r16, t312-Expiry-r16, spare}, + measResultFreqListMRDC MeasResultFreqListFailMRDC OPTIONAL, + measResultSCG-FailureMRDC OCTET STRING OPTIONAL, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL + ]] +} + +MeasResultFreqListFailMRDC ::= SEQUENCE (SIZE (1.. maxFreq)) OF MeasResult2EUTRA + +-- TAG-SCGFAILUREINFORMATIONEUTRA-STOP +-- TAG-SECURITYMODECOMMAND-START + +SecurityModeCommand ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeCommand SecurityModeCommand-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeCommand-IEs ::= SEQUENCE { + securityConfigSMC SecurityConfigSMC, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +SecurityConfigSMC ::= SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig, + ... +} + +-- TAG-SECURITYMODECOMMAND-STOP +-- TAG-SECURITYMODECOMPLETE-START + +SecurityModeComplete ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeComplete SecurityModeComplete-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeComplete-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-SECURITYMODECOMPLETE-STOP +-- TAG-SECURITYMODEFAILURE-START + +SecurityModeFailure ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + securityModeFailure SecurityModeFailure-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SecurityModeFailure-IEs ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-SECURITYMODEFAILURE-STOP +-- TAG-SIB1-START + +SIB1 ::= SEQUENCE { + cellSelectionInfo SEQUENCE { + q-RxLevMin Q-RxLevMin, + q-RxLevMinOffset INTEGER (1..8) OPTIONAL, -- Need S + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + q-QualMinOffset INTEGER (1..8) OPTIONAL -- Need S + } OPTIONAL, -- Cond Standalone + cellAccessRelatedInfo CellAccessRelatedInfo, + connEstFailureControl ConnEstFailureControl OPTIONAL, -- Need R + si-SchedulingInfo SI-SchedulingInfo OPTIONAL, -- Need R + servingCellConfigCommon ServingCellConfigCommonSIB OPTIONAL, -- Need R + ims-EmergencySupport ENUMERATED {true} OPTIONAL, -- Need R + eCallOverIMS-Support ENUMERATED {true} OPTIONAL, -- Need R + ue-TimersAndConstants UE-TimersAndConstants OPTIONAL, -- Need R + uac-BarringInfo SEQUENCE { + uac-BarringForCommon UAC-BarringPerCatList OPTIONAL, -- Need S + uac-BarringPerPLMN-List UAC-BarringPerPLMN-List OPTIONAL, -- Need S + uac-BarringInfoSetList UAC-BarringInfoSetList, + uac-AccessCategory1-SelectionAssistanceInfo CHOICE { + plmnCommon UAC-AccessCategory1-SelectionAssistanceInfo, + individualPLMNList SEQUENCE (SIZE (2..maxPLMN)) OF UAC-AccessCategory1-SelectionAssistanceInfo + } OPTIONAL -- Need S + } OPTIONAL, -- Need R + useFullResumeID ENUMERATED {true} OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SIB1-v1610-IEs OPTIONAL +} + +SIB1-v1610-IEs ::= SEQUENCE { + idleModeMeasurementsEUTRA-r16 ENUMERATED{true} OPTIONAL, -- Need R + idleModeMeasurementsNR-r16 ENUMERATED{true} OPTIONAL, -- Need R + posSI-SchedulingInfo-r16 PosSI-SchedulingInfo-r16 OPTIONAL, -- Need R + nonCriticalExtension SIB1-v1630-IEs OPTIONAL +} + +SIB1-v1630-IEs ::= SEQUENCE { + uac-BarringInfo-v1630 SEQUENCE { + uac-AC1-SelectAssistInfo-r16 SEQUENCE (SIZE (2..maxPLMN)) OF UAC-AC1-SelectAssistInfo-r16 + } OPTIONAL, -- Need R + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UAC-AccessCategory1-SelectionAssistanceInfo ::= ENUMERATED {a, b, c} + +UAC-AC1-SelectAssistInfo-r16 ::= ENUMERATED {a, b, c, notConfigured} + +-- TAG-SIB1-STOP +-- TAG-SIDELINKUEINFORMATIONNR-START + +SidelinkUEInformationNR-r16::= SEQUENCE { + criticalExtensions CHOICE { + sidelinkUEInformationNR-r16 SidelinkUEInformationNR-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +SidelinkUEInformationNR-r16-IEs ::= SEQUENCE { + sl-RxInterestedFreqList-r16 SL-InterestedFreqList-r16 OPTIONAL, + sl-TxResourceReqList-r16 SL-TxResourceReqList-r16 OPTIONAL, + sl-FailureList-r16 SL-FailureList-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SL-InterestedFreqList-r16 ::= SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF INTEGER (1..maxNrofFreqSL-r16) + +SL-TxResourceReqList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-TxResourceReq-r16 + +SL-TxResourceReq-r16 ::= SEQUENCE { + sl-DestinationIdentity-r16 SL-DestinationIdentity-r16, + sl-CastType-r16 ENUMERATED {broadcast, groupcast, unicast, spare1}, + sl-RLC-ModeIndicationList-r16 SEQUENCE (SIZE (1.. maxNrofSLRB-r16)) OF SL-RLC-ModeIndication-r16 OPTIONAL, + sl-QoS-InfoList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIsPerDest-r16)) OF SL-QoS-Info-r16 OPTIONAL, + sl-TypeTxSyncList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-TypeTxSync-r16 OPTIONAL, + sl-TxInterestedFreqList-r16 SL-TxInterestedFreqList-r16 OPTIONAL, + sl-CapabilityInformationSidelink-r16 OCTET STRING OPTIONAL +} + +SL-TxInterestedFreqList-r16 ::= SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF INTEGER (1..maxNrofFreqSL-r16) + +SL-QoS-Info-r16 ::= SEQUENCE { + sl-QoS-FlowIdentity-r16 SL-QoS-FlowIdentity-r16, + sl-QoS-Profile-r16 SL-QoS-Profile-r16 OPTIONAL +} + +SL-RLC-ModeIndication-r16 ::= SEQUENCE { + sl-Mode-r16 CHOICE { + sl-AM-Mode-r16 NULL, + sl-UM-Mode-r16 NULL + }, + sl-QoS-InfoList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIsPerDest-r16)) OF SL-QoS-Info-r16 +} + +SL-FailureList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-Failure-r16 + +SL-Failure-r16 ::= SEQUENCE { + sl-DestinationIdentity-r16 SL-DestinationIdentity-r16, + sl-Failure-r16 ENUMERATED {rlf,configFailure, spare6, spare5, spare4, spare3, spare2, spare1} +} + +-- TAG-SIDELINKUEINFORMATIONNR-STOP +-- TAG-SYSTEMINFORMATION-START + +SystemInformation ::= SEQUENCE { + criticalExtensions CHOICE { + systemInformation SystemInformation-IEs, + criticalExtensionsFuture-r16 CHOICE { + posSystemInformation-r16 PosSystemInformation-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } + } +} + +SystemInformation-IEs ::= SEQUENCE { + sib-TypeAndInfo SEQUENCE (SIZE (1..maxSIB)) OF CHOICE { + sib2 SIB2, + sib3 SIB3, + sib4 SIB4, + sib5 SIB5, + sib6 SIB6, + sib7 SIB7, + sib8 SIB8, + sib9 SIB9, + ..., + sib10-v1610 SIB10-r16, + sib11-v1610 SIB11-r16, + sib12-v1610 SIB12-r16, + sib13-v1610 SIB13-r16, + sib14-v1610 SIB14-r16 + }, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-SYSTEMINFORMATION-STOP +-- TAG-UEASSISTANCEINFORMATION-START + +UEAssistanceInformation ::= SEQUENCE { + criticalExtensions CHOICE { + ueAssistanceInformation UEAssistanceInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEAssistanceInformation-IEs ::= SEQUENCE { + delayBudgetReport DelayBudgetReport OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UEAssistanceInformation-v1540-IEs OPTIONAL +} + +DelayBudgetReport::= CHOICE { + type1 ENUMERATED { + msMinus1280, msMinus640, msMinus320, msMinus160,msMinus80, msMinus60, msMinus40, + msMinus20, ms0, ms20,ms40, ms60, ms80, ms160, ms320, ms640, ms1280}, + ... +} + +UEAssistanceInformation-v1540-IEs ::= SEQUENCE { + overheatingAssistance OverheatingAssistance OPTIONAL, + nonCriticalExtension UEAssistanceInformation-v1610-IEs OPTIONAL +} + +OverheatingAssistance ::= SEQUENCE { + reducedMaxCCs ReducedMaxCCs-r16 OPTIONAL, + reducedMaxBW-FR1 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxBW-FR2 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxMIMO-LayersFR1 SEQUENCE { + reducedMIMO-LayersFR1-DL MIMO-LayersDL, + reducedMIMO-LayersFR1-UL MIMO-LayersUL + } OPTIONAL, + reducedMaxMIMO-LayersFR2 SEQUENCE { + reducedMIMO-LayersFR2-DL MIMO-LayersDL, + reducedMIMO-LayersFR2-UL MIMO-LayersUL + } OPTIONAL +} + +ReducedAggregatedBandwidth ::= ENUMERATED {mhz0, mhz10, mhz20, mhz30, mhz40, mhz50, mhz60, mhz80, mhz100, mhz200, mhz300, mhz400} + +UEAssistanceInformation-v1610-IEs ::= SEQUENCE { + idc-Assistance-r16 IDC-Assistance-r16 OPTIONAL, + drx-Preference-r16 DRX-Preference-r16 OPTIONAL, + maxBW-Preference-r16 MaxBW-Preference-r16 OPTIONAL, + maxCC-Preference-r16 MaxCC-Preference-r16 OPTIONAL, + maxMIMO-LayerPreference-r16 MaxMIMO-LayerPreference-r16 OPTIONAL, + minSchedulingOffsetPreference-r16 MinSchedulingOffsetPreference-r16 OPTIONAL, + releasePreference-r16 ReleasePreference-r16 OPTIONAL, + sl-UE-AssistanceInformationNR-r16 SL-UE-AssistanceInformationNR-r16 OPTIONAL, + referenceTimeInfoPreference-r16 BOOLEAN OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +IDC-Assistance-r16 ::= SEQUENCE { + affectedCarrierFreqList-r16 AffectedCarrierFreqList-r16 OPTIONAL, + affectedCarrierFreqCombList-r16 AffectedCarrierFreqCombList-r16 OPTIONAL, + ... +} + +AffectedCarrierFreqList-r16 ::= SEQUENCE (SIZE (1.. maxFreqIDC-r16)) OF AffectedCarrierFreq-r16 + +AffectedCarrierFreq-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + interferenceDirection-r16 ENUMERATED {nr, other, both, spare} +} + +AffectedCarrierFreqCombList-r16 ::= SEQUENCE (SIZE (1..maxCombIDC-r16)) OF AffectedCarrierFreqComb-r16 + +AffectedCarrierFreqComb-r16 ::= SEQUENCE { + affectedCarrierFreqComb-r16 SEQUENCE (SIZE (2..maxNrofServingCells)) OF ARFCN-ValueNR OPTIONAL, + victimSystemType-r16 VictimSystemType-r16 +} + +VictimSystemType-r16 ::= SEQUENCE { + gps-r16 ENUMERATED {true} OPTIONAL, + glonass-r16 ENUMERATED {true} OPTIONAL, + bds-r16 ENUMERATED {true} OPTIONAL, + galileo-r16 ENUMERATED {true} OPTIONAL, + navIC-r16 ENUMERATED {true} OPTIONAL, + wlan-r16 ENUMERATED {true} OPTIONAL, + bluetooth-r16 ENUMERATED {true} OPTIONAL, + ... +} + +DRX-Preference-r16 ::= SEQUENCE { + preferredDRX-InactivityTimer-r16 ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1} OPTIONAL, + preferredDRX-LongCycle-r16 ENUMERATED { + ms10, ms20, ms32, ms40, ms60, ms64, ms70, ms80, ms128, ms160, ms256, ms320, ms512, + ms640, ms1024, ms1280, ms2048, ms2560, ms5120, ms10240, spare12, spare11, spare10, + spare9, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, + preferredDRX-ShortCycle-r16 ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, + preferredDRX-ShortCycleTimer-r16 INTEGER (1..16) OPTIONAL +} + +MaxBW-Preference-r16 ::= SEQUENCE { + reducedMaxBW-FR1-r16 ReducedMaxBW-FRx-r16 OPTIONAL, + reducedMaxBW-FR2-r16 ReducedMaxBW-FRx-r16 OPTIONAL +} + +MaxCC-Preference-r16 ::= SEQUENCE { + reducedMaxCCs-r16 ReducedMaxCCs-r16 OPTIONAL +} + +MaxMIMO-LayerPreference-r16 ::= SEQUENCE { + reducedMaxMIMO-LayersFR1-r16 SEQUENCE { + reducedMIMO-LayersFR1-DL-r16 INTEGER (1..8), + reducedMIMO-LayersFR1-UL-r16 INTEGER (1..4) + } OPTIONAL, + reducedMaxMIMO-LayersFR2-r16 SEQUENCE { + reducedMIMO-LayersFR2-DL-r16 INTEGER (1..8), + reducedMIMO-LayersFR2-UL-r16 INTEGER (1..4) + } OPTIONAL +} + +MinSchedulingOffsetPreference-r16 ::= SEQUENCE { + preferredK0-r16 SEQUENCE { + preferredK0-SCS-15kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK0-SCS-30kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK0-SCS-60kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL, + preferredK0-SCS-120kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL + } OPTIONAL, + preferredK2-r16 SEQUENCE { + preferredK2-SCS-15kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK2-SCS-30kHz-r16 ENUMERATED {sl1, sl2, sl4, sl6} OPTIONAL, + preferredK2-SCS-60kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL, + preferredK2-SCS-120kHz-r16 ENUMERATED {sl2, sl4, sl8, sl12} OPTIONAL + } OPTIONAL +} + +ReleasePreference-r16 ::= SEQUENCE { + preferredRRC-State-r16 ENUMERATED {idle, inactive, connected, outOfConnected} +} + +ReducedMaxBW-FRx-r16 ::= SEQUENCE { + reducedBW-DL-r16 ReducedAggregatedBandwidth, + reducedBW-UL-r16 ReducedAggregatedBandwidth +} + +ReducedMaxCCs-r16 ::= SEQUENCE { + reducedCCsDL-r16 INTEGER (0..31), + reducedCCsUL-r16 INTEGER (0..31) +} + +SL-UE-AssistanceInformationNR-r16 ::= SEQUENCE (SIZE (1..maxNrofTrafficPattern-r16)) OF SL-TrafficPatternInfo-r16 + +SL-TrafficPatternInfo-r16::= SEQUENCE { + trafficPeriodicity-r16 ENUMERATED {ms20, ms50, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}, + timingOffset-r16 INTEGER (0..10239), + messageSize-r16 BIT STRING (SIZE (8)), + sl-QoS-FlowIdentity-r16 SL-QoS-FlowIdentity-r16 +} + +-- TAG-UEASSISTANCEINFORMATION-STOP +-- TAG-UECAPABILITYENQUIRY-START + +UECapabilityEnquiry ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityEnquiry UECapabilityEnquiry-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityEnquiry-IEs ::= SEQUENCE { + ue-CapabilityRAT-RequestList UE-CapabilityRAT-RequestList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ue-CapabilityEnquiryExt OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL +} + +UECapabilityEnquiry-v1560-IEs ::= SEQUENCE { + capabilityRequestFilterCommon UE-CapabilityRequestFilterCommon OPTIONAL, -- Need N + nonCriticalExtension UECapabilityEnquiry-v1610-IEs OPTIONAL +} + +UECapabilityEnquiry-v1610-IEs ::= SEQUENCE { + rrc-SegAllowed-r16 ENUMERATED {enabled} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UECAPABILITYENQUIRY-STOP +-- TAG-UECAPABILITYINFORMATION-START + +UECapabilityInformation ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityInformation UECapabilityInformation-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityInformation-IEs ::= SEQUENCE { + ue-CapabilityRAT-ContainerList UE-CapabilityRAT-ContainerList OPTIONAL, + + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-UECAPABILITYINFORMATION-STOP +-- TAG-UEINFORMATIONREQUEST-START + +UEInformationRequest-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueInformationRequest-r16 UEInformationRequest-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEInformationRequest-r16-IEs ::= SEQUENCE { + idleModeMeasurementReq-r16 ENUMERATED{true} OPTIONAL, -- Need N + logMeasReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + connEstFailReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + ra-ReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + rlf-ReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + mobilityHistoryReportReq-r16 ENUMERATED {true} OPTIONAL, -- Need N + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UEINFORMATIONREQUEST-STOP +-- TAG-UEINFORMATIONRESPONSE-START + +UEInformationResponse-r16 ::= SEQUENCE { + rrc-TransactionIdentifier RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueInformationResponse-r16 UEInformationResponse-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +UEInformationResponse-r16-IEs ::= SEQUENCE { + measResultIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL, + measResultIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + logMeasReport-r16 LogMeasReport-r16 OPTIONAL, + connEstFailReport-r16 ConnEstFailReport-r16 OPTIONAL, + ra-ReportList-r16 RA-ReportList-r16 OPTIONAL, + rlf-Report-r16 RLF-Report-r16 OPTIONAL, + mobilityHistoryReport-r16 MobilityHistoryReport-r16 OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +LogMeasReport-r16 ::= SEQUENCE { + absoluteTimeStamp-r16 AbsoluteTimeInfo-r16, + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + logMeasInfoList-r16 LogMeasInfoList-r16, + logMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableBT-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableWLAN-r16 ENUMERATED {true} OPTIONAL, + ... +} + +LogMeasInfoList-r16 ::= SEQUENCE (SIZE (1..maxLogMeasReport-r16)) OF LogMeasInfo-r16 + +LogMeasInfo-r16 ::= SEQUENCE { + locationInfo-r16 LocationInfo-r16 OPTIONAL, + relativeTimeStamp-r16 INTEGER (0..7200), + servCellIdentity-r16 CGI-Info-Logging-r16 OPTIONAL, + measResultServingCell-r16 MeasResultServingCell-r16 OPTIONAL, + measResultNeighCells-r16 SEQUENCE { + measResultNeighCellListNR MeasResultListLogging2NR-r16 OPTIONAL, + measResultNeighCellListEUTRA MeasResultList2EUTRA-r16 OPTIONAL + }, + anyCellSelectionDetected-r16 ENUMERATED {true} OPTIONAL, + ... +} + +ConnEstFailReport-r16 ::= SEQUENCE { + measResultFailedCell-r16 MeasResultFailedCell-r16, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + measResultNeighCells-r16 SEQUENCE { + measResultNeighCellListNR MeasResultList2NR-r16 OPTIONAL, + measResultNeighCellListEUTRA MeasResultList2EUTRA-r16 OPTIONAL + }, + numberOfConnFail-r16 INTEGER (1..8), + perRAInfoList-r16 PerRAInfoList-r16, + timeSinceFailure-r16 TimeSinceFailure-r16, + ... +} + +MeasResultServingCell-r16 ::= SEQUENCE { + resultsSSB-Cell MeasQuantityResults, + resultsSSB SEQUENCE{ + best-ssb-Index SSB-Index, + best-ssb-Results MeasQuantityResults, + numberOfGoodSSB INTEGER (1..maxNrofSSBs-r16) + } OPTIONAL +} + +MeasResultFailedCell-r16 ::= SEQUENCE { + cgi-Info CGI-Info-Logging-r16, + measResult-r16 SEQUENCE { + cellResults-r16 SEQUENCE{ + resultsSSB-Cell-r16 MeasQuantityResults + }, + rsIndexResults-r16 SEQUENCE{ + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList + } + } +} + +RA-ReportList-r16 ::= SEQUENCE (SIZE (1..maxRAReport-r16)) OF RA-Report-r16 + +RA-Report-r16 ::= SEQUENCE { + cellId-r16 CHOICE { + cellGlobalId-r16 CGI-Info-Logging-r16, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 PhysCellId, + carrierFreq-r16 ARFCN-ValueNR + } + }, + ra-InformationCommon-r16 RA-InformationCommon-r16 OPTIONAL, + raPurpose-r16 ENUMERATED {accessRelated, beamFailureRecovery, reconfigurationWithSync, ulUnSynchronized, + schedulingRequestFailure, noPUCCHResourceAvailable, requestForOtherSI, + spare9, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1}, + ... +} + +RA-InformationCommon-r16 ::= SEQUENCE { + absoluteFrequencyPointA-r16 ARFCN-ValueNR, + locationAndBandwidth-r16 INTEGER (0..37949), + subcarrierSpacing-r16 SubcarrierSpacing, + msg1-FrequencyStart-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, + msg1-FrequencyStartCFRA-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, + msg1-SubcarrierSpacing-r16 SubcarrierSpacing OPTIONAL, + msg1-SubcarrierSpacingCFRA-r16 SubcarrierSpacing OPTIONAL, + msg1-FDM-r16 ENUMERATED {one, two, four, eight} OPTIONAL, + msg1-FDMCFRA-r16 ENUMERATED {one, two, four, eight} OPTIONAL, + perRAInfoList-r16 PerRAInfoList-r16, + ... +} + +PerRAInfoList-r16 ::= SEQUENCE (SIZE (1..200)) OF PerRAInfo-r16 + +PerRAInfo-r16 ::= CHOICE { + perRASSBInfoList-r16 PerRASSBInfo-r16, + perRACSI-RSInfoList-r16 PerRACSI-RSInfo-r16 +} + +PerRASSBInfo-r16 ::= SEQUENCE { + ssb-Index-r16 SSB-Index, + numberOfPreamblesSentOnSSB-r16 INTEGER (1..200), + perRAAttemptInfoList-r16 PerRAAttemptInfoList-r16 +} + +PerRACSI-RSInfo-r16 ::= SEQUENCE { + csi-RS-Index-r16 CSI-RS-Index, + numberOfPreamblesSentOnCSI-RS-r16 INTEGER (1..200) +} + +PerRAAttemptInfoList-r16 ::= SEQUENCE (SIZE (1..200)) OF PerRAAttemptInfo-r16 + +PerRAAttemptInfo-r16 ::= SEQUENCE { + contentionDetected-r16 BOOLEAN OPTIONAL, + dlRSRPAboveThreshold-r16 BOOLEAN OPTIONAL, + ... +} + +RLF-Report-r16 ::= CHOICE { + nr-RLF-Report-r16 SEQUENCE { + measResultLastServCell-r16 MeasResultRLFNR-r16, + measResultNeighCells-r16 SEQUENCE { + measResultListNR-r16 MeasResultList2NR-r16 OPTIONAL, + measResultListEUTRA-r16 MeasResultList2EUTRA-r16 OPTIONAL + } OPTIONAL, + c-RNTI-r16 RNTI-Value, + previousPCellId-r16 CHOICE { + nrPreviousCell-r16 CGI-Info-Logging-r16, + eutraPreviousCell-r16 CGI-InfoEUTRALogging + } OPTIONAL, + failedPCellId-r16 CHOICE { + nrFailedPCellId-r16 CHOICE { + cellGlobalId-r16 CGI-Info-Logging-r16, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 PhysCellId, + carrierFreq-r16 ARFCN-ValueNR + } + }, + eutraFailedPCellId-r16 CHOICE { + cellGlobalId-r16 CGI-InfoEUTRALogging, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 EUTRA-PhysCellId, + carrierFreq-r16 ARFCN-ValueEUTRA + } + } + }, + reconnectCellId-r16 CHOICE { + nrReconnectCellId-r16 CGI-Info-Logging-r16, + eutraReconnectCellId-r16 CGI-InfoEUTRALogging + } OPTIONAL, + timeUntilReconnection-16 TimeUntilReconnection-16 OPTIONAL, + reestablishmentCellId-r16 CGI-Info-Logging-r16 OPTIONAL, + timeConnFailure-r16 INTEGER (0..1023) OPTIONAL, + timeSinceFailure-r16 TimeSinceFailure-r16, + connectionFailureType-r16 ENUMERATED {rlf, hof}, + rlf-Cause-r16 ENUMERATED {t310-Expiry, randomAccessProblem, rlc-MaxNumRetx, + beamFailureRecoveryFailure, lbtFailure-r16, + bh-rlfRecoveryFailure, spare2, spare1}, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + noSuitableCellFound-r16 ENUMERATED {true} OPTIONAL, + ra-InformationCommon-r16 RA-InformationCommon-r16 OPTIONAL, + ... + }, + eutra-RLF-Report-r16 SEQUENCE { + failedPCellId-EUTRA CGI-InfoEUTRALogging, + measResult-RLF-Report-EUTRA-r16 OCTET STRING, + ... + } +} + +MeasResultList2NR-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResult2NR-r16 +MeasResultList2EUTRA-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResult2EUTRA-r16 + +MeasResult2NR-r16 ::= SEQUENCE { + ssbFrequency-r16 ARFCN-ValueNR OPTIONAL, + refFreqCSI-RS-r16 ARFCN-ValueNR OPTIONAL, + measResultList-r16 MeasResultListNR +} + +MeasResultListLogging2NR-r16 ::= SEQUENCE(SIZE (1..maxFreq)) OF MeasResultLogging2NR-r16 + +MeasResultLogging2NR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + measResultListLoggingNR-r16 MeasResultListLoggingNR-r16 +} + +MeasResultListLoggingNR-r16 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultLoggingNR-r16 + +MeasResultLoggingNR-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + resultsSSB-Cell-r16 MeasQuantityResults, + numberOfGoodSSB-r16 INTEGER (1..maxNrofSSBs-r16) OPTIONAL +} + +MeasResult2EUTRA-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueEUTRA, + measResultList-r16 MeasResultListEUTRA +} + +MeasResultRLFNR-r16 ::= SEQUENCE { + measResult-r16 SEQUENCE { + cellResults-r16 SEQUENCE{ + resultsSSB-Cell-r16 MeasQuantityResults OPTIONAL, + resultsCSI-RS-Cell-r16 MeasQuantityResults OPTIONAL + }, + rsIndexResults-r16 SEQUENCE{ + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList OPTIONAL, + ssbRLMConfigBitmap-r16 BIT STRING (SIZE (64)) OPTIONAL, + resultsCSI-RS-Indexes-r16 ResultsPerCSI-RS-IndexList OPTIONAL, + csi-rsRLMConfigBitmap-r16 BIT STRING (SIZE (96)) OPTIONAL + } OPTIONAL + } +} + +TimeSinceFailure-r16 ::= INTEGER (0..172800) + +MobilityHistoryReport-r16 ::= VisitedCellInfoList-r16 + +TimeUntilReconnection-16 ::= INTEGER (0..172800) + +-- TAG-UEINFORMATIONRESPONSE-STOP +-- TAG-ULDEDICATEDMESSAGESEGMENT-START + +ULDedicatedMessageSegment-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + ulDedicatedMessageSegment-r16 ULDedicatedMessageSegment-r16-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULDedicatedMessageSegment-r16-IEs ::= SEQUENCE { + segmentNumber-r16 INTEGER (0..15), + rrc-MessageSegmentContainer-r16 OCTET STRING, + rrc-MessageSegmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULDEDICATEDMESSAGESEGMENT-STOP +-- TAG-ULINFORMATIONTRANSFER-START + +ULInformationTransfer ::= SEQUENCE { + criticalExtensions CHOICE { + ulInformationTransfer ULInformationTransfer-IEs, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransfer-IEs ::= SEQUENCE { + dedicatedNAS-Message DedicatedNAS-Message OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFER-STOP +-- TAG-ULINFORMATIONTRANSFERIRAT-START + +ULInformationTransferIRAT-r16 ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ulInformationTransferIRAT-r16 ULInformationTransferIRAT-r16-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransferIRAT-r16-IEs ::= SEQUENCE { + ul-DCCH-MessageEUTRA-r16 OCTET STRING OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFERIRAT-STOP +-- TAG-ULINFORMATIONTRANSFERMRDC-START + +ULInformationTransferMRDC ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE { + ulInformationTransferMRDC ULInformationTransferMRDC-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +ULInformationTransferMRDC-IEs::= SEQUENCE { + ul-DCCH-MessageNR OCTET STRING OPTIONAL, + ul-DCCH-MessageEUTRA OCTET STRING OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-ULINFORMATIONTRANSFERMRDC-STOP +-- TAG-SETUPRELEASE-START + +SetupRelease { ElementTypeParam } ::= CHOICE { + release NULL, + setup ElementTypeParam +} + +-- TAG-SETUPRELEASE-STOP +-- TAG-SIB2-START + +SIB2 ::= SEQUENCE { + cellReselectionInfoCommon SEQUENCE { + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need S + rangeToBestCell RangeToBestCell OPTIONAL, -- Need R + q-Hyst ENUMERATED { + dB0, dB1, dB2, dB3, dB4, dB5, dB6, dB8, dB10, + dB12, dB14, dB16, dB18, dB20, dB22, dB24}, + speedStateReselectionPars SEQUENCE { + mobilityStateParameters MobilityStateParameters, + q-HystSF SEQUENCE { + sf-Medium ENUMERATED {dB-6, dB-4, dB-2, dB0}, + sf-High ENUMERATED {dB-6, dB-4, dB-2, dB0} + } + } OPTIONAL, -- Need R + ... + }, + cellReselectionServingFreqInfo SEQUENCE { + s-NonIntraSearchP ReselectionThreshold OPTIONAL, -- Need S + s-NonIntraSearchQ ReselectionThresholdQ OPTIONAL, -- Need S + threshServingLowP ReselectionThreshold, + threshServingLowQ ReselectionThresholdQ OPTIONAL, -- Need R + cellReselectionPriority CellReselectionPriority, + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + ... + }, + intraFreqCellReselectionInfo SEQUENCE { + q-RxLevMin Q-RxLevMin, + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + s-IntraSearchP ReselectionThreshold, + s-IntraSearchQ ReselectionThresholdQ OPTIONAL, -- Need S + t-ReselectionNR T-Reselection, + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Need S + frequencyBandListSUL MultiFrequencyBandListNR-SIB OPTIONAL, -- Need R + p-Max P-Max OPTIONAL, -- Need S + smtc SSB-MTC OPTIONAL, -- Need S + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, -- Need R + ssb-ToMeasure SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell BOOLEAN, + ..., + [[ + t-ReselectionNR-SF SpeedStateScaleFactors OPTIONAL -- Need N + ]], + [[ + smtc2-LP-r16 SSB-MTC2-LP-r16 OPTIONAL, -- Need R + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum + ]] + }, + ..., + [[ + relaxedMeasurement-r16 SEQUENCE { + lowMobilityEvaluation-r16 SEQUENCE { + s-SearchDeltaP-r16 ENUMERATED { + dB3, dB6, dB9, dB12, dB15, + spare3, spare2, spare1}, + t-SearchDeltaP-r16 ENUMERATED { + s5, s10, s20, s30, s60, s120, s180, + s240, s300, spare7, spare6, spare5, + spare4, spare3, spare2, spare1} + } OPTIONAL, -- Need R + cellEdgeEvaluation-r16 SEQUENCE { + s-SearchThresholdP-r16 ReselectionThreshold, + s-SearchThresholdQ-r16 ReselectionThresholdQ OPTIONAL -- Need R + } OPTIONAL, -- Need R + combineRelaxedMeasCondition-r16 ENUMERATED {true} OPTIONAL, -- Need R + highPriorityMeasRelax-r16 ENUMERATED {true} OPTIONAL -- Need R + } OPTIONAL -- Need R + ]] +} + +RangeToBestCell ::= Q-OffsetRange + +-- TAG-SIB2-STOP +-- TAG-SIB3-START + +SIB3 ::= SEQUENCE { + intraFreqNeighCellList IntraFreqNeighCellList OPTIONAL, -- Need R + intraFreqBlackCellList IntraFreqBlackCellList OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + intraFreqNeighCellList-v1610 IntraFreqNeighCellList-v1610 OPTIONAL, -- Need R + intraFreqWhiteCellList-r16 IntraFreqWhiteCellList-r16 OPTIONAL, -- Cond SharedSpectrum2 + intraFreqCAG-CellList-r16 SEQUENCE (SIZE (1..maxPLMN)) OF IntraFreqCAG-CellListPerPLMN-r16 OPTIONAL -- Need R + ]] +} + + +IntraFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo + +IntraFreqNeighCellList-v1610::= SEQUENCE (SIZE (1..maxCellIntra)) OF IntraFreqNeighCellInfo-v1610 + +IntraFreqNeighCellInfo ::= SEQUENCE { + physCellId PhysCellId, + q-OffsetCell Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-RxLevMinOffsetCellSUL INTEGER (1..8) OPTIONAL, -- Need R + q-QualMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + ... +} + +IntraFreqNeighCellInfo-v1610 ::= SEQUENCE { + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum2 +} + +IntraFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PCI-Range + +IntraFreqWhiteCellList-r16 ::= SEQUENCE (SIZE (1..maxCellWhite)) OF PCI-Range + +IntraFreqCAG-CellListPerPLMN-r16 ::= SEQUENCE { + plmn-IdentityIndex-r16 INTEGER (1..maxPLMN), + cag-CellList-r16 SEQUENCE (SIZE (1..maxCAG-Cell-r16)) OF PCI-Range +} + +-- TAG-SIB3-STOP +-- TAG-SIB4-START + +SIB4 ::= SEQUENCE { + interFreqCarrierFreqList InterFreqCarrierFreqList, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + interFreqCarrierFreqList-v1610 InterFreqCarrierFreqList-v1610 OPTIONAL -- Need R + ]] +} + +InterFreqCarrierFreqList ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo + +InterFreqCarrierFreqList-v1610 ::= SEQUENCE (SIZE (1..maxFreq)) OF InterFreqCarrierFreqInfo-v1610 + +InterFreqCarrierFreqInfo ::= SEQUENCE { + dl-CarrierFreq ARFCN-ValueNR, + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Cond Mandatory + frequencyBandListSUL MultiFrequencyBandListNR-SIB OPTIONAL, -- Need R + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need S + smtc SSB-MTC OPTIONAL, -- Need S + ssbSubcarrierSpacing SubcarrierSpacing, + ssb-ToMeasure SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell BOOLEAN, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, + q-RxLevMin Q-RxLevMin, + q-RxLevMinSUL Q-RxLevMin OPTIONAL, -- Need R + q-QualMin Q-QualMin OPTIONAL, -- Need S + p-Max P-Max OPTIONAL, -- Need S + t-ReselectionNR T-Reselection, + t-ReselectionNR-SF SpeedStateScaleFactors OPTIONAL, -- Need S + threshX-HighP ReselectionThreshold, + threshX-LowP ReselectionThreshold, + threshX-Q SEQUENCE { + threshX-HighQ ReselectionThresholdQ, + threshX-LowQ ReselectionThresholdQ + } OPTIONAL, -- Cond RSRQ + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need R + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + q-OffsetFreq Q-OffsetRange DEFAULT dB0, + interFreqNeighCellList InterFreqNeighCellList OPTIONAL, -- Need R + interFreqBlackCellList InterFreqBlackCellList OPTIONAL, -- Need R + ... +} + +InterFreqCarrierFreqInfo-v1610 ::= SEQUENCE { + interFreqNeighCellList-v1610 InterFreqNeighCellList-v1610 OPTIONAL, -- Need R + smtc2-LP-r16 SSB-MTC2-LP-r16 OPTIONAL, -- Need R + interFreqWhiteCellList-r16 InterFreqWhiteCellList-r16 OPTIONAL, -- Cond SharedSpectrum2 + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + interFreqCAG-CellList-r16 SEQUENCE (SIZE (1..maxPLMN)) OF InterFreqCAG-CellListPerPLMN-r16 OPTIONAL -- Need R +} + +InterFreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo + +InterFreqNeighCellList-v1610 ::= SEQUENCE (SIZE (1..maxCellInter)) OF InterFreqNeighCellInfo-v1610 + +InterFreqNeighCellInfo ::= SEQUENCE { + physCellId PhysCellId, + q-OffsetCell Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-RxLevMinOffsetCellSUL INTEGER (1..8) OPTIONAL, -- Need R + q-QualMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + ... +} + +InterFreqNeighCellInfo-v1610 ::= SEQUENCE { + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL -- Cond SharedSpectrum2 +} + +InterFreqBlackCellList ::= SEQUENCE (SIZE (1..maxCellBlack)) OF PCI-Range + +InterFreqWhiteCellList-r16 ::= SEQUENCE (SIZE (1..maxCellWhite)) OF PCI-Range + +InterFreqCAG-CellListPerPLMN-r16 ::= SEQUENCE { + plmn-IdentityIndex-r16 INTEGER (1..maxPLMN), + cag-CellList-r16 SEQUENCE (SIZE (1..maxCAG-Cell-r16)) OF PCI-Range +} + +-- TAG-SIB4-STOP +-- TAG-SIB5-START + +SIB5 ::= SEQUENCE { + carrierFreqListEUTRA CarrierFreqListEUTRA OPTIONAL, -- Need R + t-ReselectionEUTRA T-Reselection, + t-ReselectionEUTRA-SF SpeedStateScaleFactors OPTIONAL, -- Need S + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + carrierFreqListEUTRA-v1610 CarrierFreqListEUTRA-v1610 OPTIONAL -- Need R + ]] +} + +CarrierFreqListEUTRA ::= SEQUENCE (SIZE (1..maxEUTRA-Carrier)) OF CarrierFreqEUTRA + +CarrierFreqListEUTRA-v1610 ::= SEQUENCE (SIZE (1..maxEUTRA-Carrier)) OF CarrierFreqEUTRA-v1610 + +CarrierFreqEUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + eutra-multiBandInfoList EUTRA-MultiBandInfoList OPTIONAL, -- Need R + eutra-FreqNeighCellList EUTRA-FreqNeighCellList OPTIONAL, -- Need R + eutra-BlackCellList EUTRA-FreqBlackCellList OPTIONAL, -- Need R + allowedMeasBandwidth EUTRA-AllowedMeasBandwidth, + presenceAntennaPort1 EUTRA-PresenceAntennaPort1, + cellReselectionPriority CellReselectionPriority OPTIONAL, -- Need R + cellReselectionSubPriority CellReselectionSubPriority OPTIONAL, -- Need R + threshX-High ReselectionThreshold, + threshX-Low ReselectionThreshold, + q-RxLevMin INTEGER (-70..-22), + q-QualMin INTEGER (-34..-3), + p-MaxEUTRA INTEGER (-30..33), + threshX-Q SEQUENCE { + threshX-HighQ ReselectionThresholdQ, + threshX-LowQ ReselectionThresholdQ + } OPTIONAL -- Cond RSRQ +} + +CarrierFreqEUTRA-v1610 ::= SEQUENCE { + highSpeedEUTRACarrier-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +EUTRA-FreqBlackCellList ::= SEQUENCE (SIZE (1..maxEUTRA-CellBlack)) OF EUTRA-PhysCellIdRange + +EUTRA-FreqNeighCellList ::= SEQUENCE (SIZE (1..maxCellEUTRA)) OF EUTRA-FreqNeighCellInfo + +EUTRA-FreqNeighCellInfo ::= SEQUENCE { + physCellId EUTRA-PhysCellId, + dummy EUTRA-Q-OffsetRange, + q-RxLevMinOffsetCell INTEGER (1..8) OPTIONAL, -- Need R + q-QualMinOffsetCell INTEGER (1..8) OPTIONAL -- Need R +} + +-- TAG-SIB5-STOP +-- TAG-SIB6-START + +SIB6 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningType OCTET STRING (SIZE (2)), + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB6-STOP +-- TAG-SIB7-START + +SIB7 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment}, + warningMessageSegmentNumber INTEGER (0..63), + warningMessageSegment OCTET STRING, + dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1 + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB7-STOP +-- TAG-SIB8-START + +SIB8 ::= SEQUENCE { + messageIdentifier BIT STRING (SIZE (16)), + serialNumber BIT STRING (SIZE (16)), + warningMessageSegmentType ENUMERATED {notLastSegment, lastSegment}, + warningMessageSegmentNumber INTEGER (0..63), + warningMessageSegment OCTET STRING, + dataCodingScheme OCTET STRING (SIZE (1)) OPTIONAL, -- Cond Segment1 + warningAreaCoordinatesSegment OCTET STRING OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB8-STOP +-- TAG-SIB9-START + +SIB9 ::= SEQUENCE { + timeInfo SEQUENCE { + timeInfoUTC INTEGER (0..549755813887), + dayLightSavingTime BIT STRING (SIZE (2)) OPTIONAL, -- Need R + leapSeconds INTEGER (-127..128) OPTIONAL, -- Need R + localTimeOffset INTEGER (-63..64) OPTIONAL -- Need R + } OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ..., + [[ + referenceTimeInfo-r16 ReferenceTimeInfo-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SIB9-STOP +-- TAG-SIB10-START + +SIB10-r16 ::= SEQUENCE { + hrnn-List-r16 HRNN-List-r16 OPTIONAL, -- Need R + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +HRNN-List-r16 ::= SEQUENCE (SIZE (1..maxNPN-r16)) OF HRNN-r16 + +HRNN-r16 ::= SEQUENCE { + hrnn-r16 OCTET STRING (SIZE(1.. maxHRNN-Len-r16)) OPTIONAL -- Need R +} + +-- TAG-SIB10-STOP +-- TAG-SIB11-START + +SIB11-r16 ::= SEQUENCE { + measIdleConfigSIB-r16 MeasIdleConfigSIB-r16 OPTIONAL, -- Need S + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB11-STOP +-- TAG-SIB12-START + +SIB12-r16 ::= SEQUENCE { + segmentNumber-r16 INTEGER (0..63), + segmentType-r16 ENUMERATED {notLastSegment, lastSegment}, + segmentContainer-r16 OCTET STRING +} + +SIB12-IEs-r16 ::= SEQUENCE { + sl-ConfigCommonNR-r16 SL-ConfigCommonNR-r16, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +SL-ConfigCommonNR-r16 ::= SEQUENCE { + sl-FreqInfoList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-FreqConfigCommon-r16 OPTIONAL, -- Need R + sl-UE-SelectedConfig-r16 SL-UE-SelectedConfig-r16 OPTIONAL, -- Need R + sl-NR-AnchorCarrierFreqList-r16 SL-NR-AnchorCarrierFreqList-r16 OPTIONAL, -- Need R + sl-EUTRA-AnchorCarrierFreqList-r16 SL-EUTRA-AnchorCarrierFreqList-r16 OPTIONAL, -- Need R + sl-RadioBearerConfigList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SL-RadioBearerConfig-r16 OPTIONAL, -- Need R + sl-RLC-BearerConfigList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfig-r16 OPTIONAL, -- Need R + sl-MeasConfigCommon-r16 SL-MeasConfigCommon-r16 OPTIONAL, -- Need R + sl-CSI-Acquisition-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + sl-OffsetDFN-r16 INTEGER (1..1000) OPTIONAL, -- Need R + t400-r16 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000} OPTIONAL, -- Need R + sl-MaxNumConsecutiveDTX-r16 ENUMERATED {n1, n2, n3, n4, n6, n8, n16, n32} OPTIONAL, -- Need R + sl-SSB-PriorityNR-r16 INTEGER (1..8) OPTIONAL -- Need R +} + +SL-NR-AnchorCarrierFreqList-r16 ::= SEQUENCE (SIZE (1..maxFreqSL-NR-r16)) OF ARFCN-ValueNR + +SL-EUTRA-AnchorCarrierFreqList-r16 ::= SEQUENCE (SIZE (1..maxFreqSL-EUTRA-r16)) OF ARFCN-ValueEUTRA + +-- TAG-SIB12-STOP +-- TAG-SIB13-START + +SIB13-r16 ::= SEQUENCE { + sl-V2X-ConfigCommon-r16 OCTET STRING, + dummy OCTET STRING, + tdd-Config-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB13-STOP +-- TAG-SIB14-START + +SIB14-r16 ::= SEQUENCE { + sl-V2X-ConfigCommonExt-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIB14-STOP +-- TAG-POSSYSTEMINFORMATION-R16-IES-START + +PosSystemInformation-r16-IEs ::= SEQUENCE { + posSIB-TypeAndInfo-r16 SEQUENCE (SIZE (1..maxSIB)) OF CHOICE { + posSib1-1-r16 SIBpos-r16, + posSib1-2-r16 SIBpos-r16, + posSib1-3-r16 SIBpos-r16, + posSib1-4-r16 SIBpos-r16, + posSib1-5-r16 SIBpos-r16, + posSib1-6-r16 SIBpos-r16, + posSib1-7-r16 SIBpos-r16, + posSib1-8-r16 SIBpos-r16, + posSib2-1-r16 SIBpos-r16, + posSib2-2-r16 SIBpos-r16, + posSib2-3-r16 SIBpos-r16, + posSib2-4-r16 SIBpos-r16, + posSib2-5-r16 SIBpos-r16, + posSib2-6-r16 SIBpos-r16, + posSib2-7-r16 SIBpos-r16, + posSib2-8-r16 SIBpos-r16, + posSib2-9-r16 SIBpos-r16, + posSib2-10-r16 SIBpos-r16, + posSib2-11-r16 SIBpos-r16, + posSib2-12-r16 SIBpos-r16, + posSib2-13-r16 SIBpos-r16, + posSib2-14-r16 SIBpos-r16, + posSib2-15-r16 SIBpos-r16, + posSib2-16-r16 SIBpos-r16, + posSib2-17-r16 SIBpos-r16, + posSib2-18-r16 SIBpos-r16, + posSib2-19-r16 SIBpos-r16, + posSib2-20-r16 SIBpos-r16, + posSib2-21-r16 SIBpos-r16, + posSib2-22-r16 SIBpos-r16, + posSib2-23-r16 SIBpos-r16, + posSib3-1-r16 SIBpos-r16, + posSib4-1-r16 SIBpos-r16, + posSib5-1-r16 SIBpos-r16, + posSib6-1-r16 SIBpos-r16, + posSib6-2-r16 SIBpos-r16, + posSib6-3-r16 SIBpos-r16, + ... + }, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-POSSYSTEMINFORMATION-R16-IES-STOP +-- TAG-POSSI-SCHEDULINGINFO-START + +PosSI-SchedulingInfo-r16 ::= SEQUENCE { + posSchedulingInfoList-r16 SEQUENCE (SIZE (1..maxSI-Message)) OF PosSchedulingInfo-r16, + posSI-RequestConfig-r16 SI-RequestConfig OPTIONAL, -- Cond MSG-1 + posSI-RequestConfigSUL-r16 SI-RequestConfig OPTIONAL, -- Cond SUL-MSG-1 + ... +} + +PosSchedulingInfo-r16 ::= SEQUENCE { + offsetToSI-Used-r16 ENUMERATED {true} OPTIONAL, -- Need R + posSI-Periodicity-r16 ENUMERATED {rf8, rf16, rf32, rf64, rf128, rf256, rf512}, + posSI-BroadcastStatus-r16 ENUMERATED {broadcasting, notBroadcasting}, + posSIB-MappingInfo-r16 PosSIB-MappingInfo-r16, + ... +} + +PosSIB-MappingInfo-r16 ::= SEQUENCE (SIZE (1..maxSIB)) OF PosSIB-Type-r16 + +PosSIB-Type-r16 ::= SEQUENCE { + encrypted-r16 ENUMERATED { true } OPTIONAL, -- Need R + gnss-id-r16 GNSS-ID-r16 OPTIONAL, -- Need R + sbas-id-r16 SBAS-ID-r16 OPTIONAL, -- Need R + posSibType-r16 ENUMERATED { posSibType1-1, posSibType1-2, posSibType1-3, posSibType1-4, posSibType1-5, posSibType1-6, + posSibType1-7, posSibType1-8, posSibType2-1, posSibType2-2, posSibType2-3, posSibType2-4, + posSibType2-5, posSibType2-6, posSibType2-7, posSibType2-8, posSibType2-9, posSibType2-10, + posSibType2-11, posSibType2-12, posSibType2-13, posSibType2-14, posSibType2-15, + posSibType2-16, posSibType2-17, posSibType2-18, posSibType2-19, posSibType2-20, + posSibType2-21, posSibType2-22, posSibType2-23, posSibType3-1, posSibType4-1, + posSibType5-1,posSibType6-1, posSibType6-2, posSibType6-3,... }, + areaScope-r16 ENUMERATED {true} OPTIONAL -- Need S +} + +GNSS-ID-r16 ::= SEQUENCE { + gnss-id-r16 ENUMERATED{gps, sbas, qzss, galileo, glonass, bds, ...}, + ... +} + +SBAS-ID-r16 ::= SEQUENCE { + sbas-id-r16 ENUMERATED { waas, egnos, msas, gagan, ...}, + ... +} + +-- TAG-POSSI-SCHEDULINGINFO-STOP +-- TAG-SIPOS-START + +SIBpos-r16 ::= SEQUENCE { + assistanceDataSIB-Element-r16 OCTET STRING, + lateNonCriticalExtension OCTET STRING OPTIONAL, + ... +} + +-- TAG-SIPOS-STOP +-- TAG-ADDITIONALSPECTRUMEMISSION-START + +AdditionalSpectrumEmission ::= INTEGER (0..7) + +-- TAG-ADDITIONALSPECTRUMEMISSION-STOP +-- TAG-ALPHA-START + +Alpha ::= ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} + +-- TAG-ALPHA-STOP +-- TAG-AMF-IDENTIFIER-START + +AMF-Identifier ::= BIT STRING (SIZE (24)) + +-- TAG-AMF-IDENTIFIER-STOP +-- TAG-ARFCN-VALUEEUTRA-START + +ARFCN-ValueEUTRA ::= INTEGER (0..maxEARFCN) + +-- TAG-ARFCN-VALUEEUTRA-STOP +-- TAG-ARFCN-VALUENR-START + +ARFCN-ValueNR ::= INTEGER (0..maxNARFCN) + +-- TAG-ARFCN-VALUENR-STOP +-- TAG-ARFCN-ValueUTRA-FDD-START + +ARFCN-ValueUTRA-FDD-r16 ::= INTEGER (0..16383) + +-- TAG-ARFCN-ValueUTRA-FDD-STOP +-- TAG-AVAILABILITYCOMBINATIONSPERCELL-START + +AvailabilityCombinationsPerCell-r16 ::= SEQUENCE { + availabilityCombinationsPerCellIndex-r16 AvailabilityCombinationsPerCellIndex-r16, + iab-DU-CellIdentity-r16 CellIdentity, + positionInDCI-AI-r16 INTEGER(0..maxAI-DCI-PayloadSize-r16-1) OPTIONAL, -- Need M + availabilityCombinations-r16 SEQUENCE (SIZE (1..maxNrofAvailabilityCombinationsPerSet-r16)) OF AvailabilityCombination-r16, + ... +} + +AvailabilityCombinationsPerCellIndex-r16 ::= INTEGER(0..maxNrofDUCells-r16) + +AvailabilityCombination-r16 ::= SEQUENCE { + availabilityCombinationId-r16 AvailabilityCombinationId-r16, + resourceAvailability-r16 SEQUENCE (SIZE (1..maxNrofResourceAvailabilityPerCombination-r16)) OF INTEGER (0..7) +} + +AvailabilityCombinationId-r16 ::= INTEGER (0..maxNrofAvailabilityCombinationsPerSet-r16-1) + +-- TAG-AVAILABILITYCOMBINATIONSPERCELL-STOP +-- TAG-AVAILABILITYINDICATOR-START + +AvailabilityIndicator-r16 ::= SEQUENCE { + ai-RNTI-r16 AI-RNTI-r16, + dci-PayloadSizeAI-r16 INTEGER (1..maxAI-DCI-PayloadSize-r16), + availableCombToAddModList-r16 SEQUENCE (SIZE(1..maxNrofDUCells-r16)) OF AvailabilityCombinationsPerCell-r16 OPTIONAL, -- Need N + availableCombToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofDUCells-r16)) OF AvailabilityCombinationsPerCellIndex-r16 OPTIONAL, -- Need N + ... +} + +AI-RNTI-r16 ::= RNTI-Value + +-- TAG-AVAILABILITYINDICATOR-STOP +-- TAG-BAPROUTINGID-START + +BAP-RoutingID-r16::= SEQUENCE{ + bap-Address-r16 BIT STRING (SIZE (10)), + bap-PathId-r16 BIT STRING (SIZE (10)) +} + +-- TAG-BAPROUTINGID-STOP +-- TAG-BEAMFAILURERECOVERYCONFIG-START + +BeamFailureRecoveryConfig ::= SEQUENCE { + rootSequenceIndex-BFR INTEGER (0..137) OPTIONAL, -- Need M + rach-ConfigBFR RACH-ConfigGeneric OPTIONAL, -- Need M + rsrp-ThresholdSSB RSRP-Range OPTIONAL, -- Need M + candidateBeamRSList SEQUENCE (SIZE(1..maxNrofCandidateBeams)) OF PRACH-ResourceDedicatedBFR OPTIONAL, -- Need M + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, + four, eight, sixteen} OPTIONAL, -- Need M + ra-ssb-OccasionMaskIndex INTEGER (0..15) OPTIONAL, -- Need M + recoverySearchSpaceId SearchSpaceId OPTIONAL, -- Need R + ra-Prioritization RA-Prioritization OPTIONAL, -- Need R + beamFailureRecoveryTimer ENUMERATED {ms10, ms20, ms40, ms60, ms80, ms100, ms150, ms200} OPTIONAL, -- Need M + ..., + [[ + msg1-SubcarrierSpacing SubcarrierSpacing OPTIONAL -- Need M + ]], + [[ + ra-PrioritizationTwoStep-r16 RA-Prioritization OPTIONAL, -- Need R + candidateBeamRSListExt-v1610 SetupRelease{ CandidateBeamRSListExt-r16 } OPTIONAL -- Need M + ]], + [[ + spCell-BFR-CBRA-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +PRACH-ResourceDedicatedBFR ::= CHOICE { + ssb BFR-SSB-Resource, + csi-RS BFR-CSIRS-Resource +} + +BFR-SSB-Resource ::= SEQUENCE { + ssb SSB-Index, + ra-PreambleIndex INTEGER (0..63), + ... +} + +BFR-CSIRS-Resource ::= SEQUENCE { + csi-RS NZP-CSI-RS-ResourceId, + ra-OccasionList SEQUENCE (SIZE(1..maxRA-OccasionsPerCSIRS)) OF INTEGER (0..maxRA-Occasions-1) OPTIONAL, -- Need R + ra-PreambleIndex INTEGER (0..63) OPTIONAL, -- Need R + ... +} + +CandidateBeamRSListExt-r16::= SEQUENCE (SIZE(1.. maxNrofCandidateBeamsExt-r16)) OF PRACH-ResourceDedicatedBFR + +-- TAG-BEAMFAILURERECOVERYCONFIG-STOP +-- TAG-BEAMFAILURERECOVERYSCELLCONFIG-START + +BeamFailureRecoverySCellConfig-r16 ::= SEQUENCE { + rsrp-ThresholdBFR-r16 RSRP-Range OPTIONAL, -- Need M + candidateBeamRSSCellList-r16 SEQUENCE (SIZE(1..maxNrofCandidateBeams-r16)) OF CandidateBeamRS-r16 OPTIONAL, -- Need M + ... +} + +CandidateBeamRS-r16 ::= SEQUENCE { + candidateBeamConfig-r16 CHOICE { + ssb-r16 SSB-Index, + csi-RS-r16 NZP-CSI-RS-ResourceId + }, + servingCellId ServCellIndex OPTIONAL -- Need R +} + +-- TAG-BEAMFAILURERECOVERYSCELLCONFIG-STOP +-- TAG-BETAOFFSETS-START + +BetaOffsets ::= SEQUENCE { + betaOffsetACK-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetACK-Index2 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetACK-Index3 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part1-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part1-Index2 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part2-Index1 INTEGER(0..31) OPTIONAL, -- Need S + betaOffsetCSI-Part2-Index2 INTEGER(0..31) OPTIONAL -- Need S +} + +-- TAG-BETAOFFSETS-STOP +-- TAG-BHLOGICALCHANNELIDENTITY-START + +BH-LogicalChannelIdentity-r16 ::= CHOICE { + bh-LogicalChannelIdentity-r16 LogicalChannelIdentity, + bh-LogicalChannelIdentityExt-r16 BH-LogicalChannelIdentity-Ext-r16 +} + +-- TAG-BHLOGICALCHANNELIDENTITY-STOP +-- TAG-BHLOGICALCHANNELIDENTITYEXT-START + +BH-LogicalChannelIdentity-Ext-r16 ::= INTEGER (320.. maxLC-ID-Iab-r16) + +-- TAG-BHLOGICALCHANNELIDENTITYEXT-STOP +-- TAG-BHRLCCHANNELCONFIG-START + +BH-RLC-ChannelConfig-r16::= SEQUENCE { + bh-LogicalChannelIdentity-r16 BH-LogicalChannelIdentity-r16 OPTIONAL, -- Cond LCH-SetupOnly + bh-RLC-ChannelID-r16 BH-RLC-ChannelID-r16, + reestablishRLC-r16 ENUMERATED {true} OPTIONAL, -- Need N + rlc-Config-r16 RLC-Config OPTIONAL, -- Cond LCH-Setup + mac-LogicalChannelConfig-r16 LogicalChannelConfig OPTIONAL, -- Cond LCH-Setup + ... +} + +-- TAG-BHRLCCHANNELCONFIG-STOP +-- TAG-BHRLCCHANNELID-START + +BH-RLC-ChannelID-r16 ::= BIT STRING (SIZE (16)) + +-- TAG-BHRLCCHANNELID-STOP +-- TAG-BSR-CONFIG-START + +BSR-Config ::= SEQUENCE { + periodicBSR-Timer ENUMERATED { sf1, sf5, sf10, sf16, sf20, sf32, sf40, sf64, + sf80, sf128, sf160, sf320, sf640, sf1280, sf2560, infinity }, + retxBSR-Timer ENUMERATED { sf10, sf20, sf40, sf80, sf160, sf320, sf640, sf1280, sf2560, + sf5120, sf10240, spare5, spare4, spare3, spare2, spare1}, + logicalChannelSR-DelayTimer ENUMERATED { sf20, sf40, sf64, sf128, sf512, sf1024, sf2560, spare1} OPTIONAL, -- Need R + ... +} + +-- TAG-BSR-CONFIG-STOP +-- TAG-BWP-START + +BWP ::= SEQUENCE { + locationAndBandwidth INTEGER (0..37949), + subcarrierSpacing SubcarrierSpacing, + cyclicPrefix ENUMERATED { extended } OPTIONAL -- Need R +} + +-- TAG-BWP-STOP +-- TAG-BWP-DOWNLINK-START + +BWP-Downlink ::= SEQUENCE { + bwp-Id BWP-Id, + bwp-Common BWP-DownlinkCommon OPTIONAL, -- Cond SetupOtherBWP + bwp-Dedicated BWP-DownlinkDedicated OPTIONAL, -- Cond SetupOtherBWP + ... +} + +-- TAG-BWP-DOWNLINK-STOP +-- TAG-BWP-DOWNLINKCOMMON-START + +BWP-DownlinkCommon ::= SEQUENCE { + genericParameters BWP, + pdcch-ConfigCommon SetupRelease { PDCCH-ConfigCommon } OPTIONAL, -- Need M + pdsch-ConfigCommon SetupRelease { PDSCH-ConfigCommon } OPTIONAL, -- Need M + ... +} + +-- TAG-BWP-DOWNLINKCOMMON-STOP +-- TAG-BWP-DOWNLINKDEDICATED-START + +BWP-DownlinkDedicated ::= SEQUENCE { + pdcch-Config SetupRelease { PDCCH-Config } OPTIONAL, -- Need M + pdsch-Config SetupRelease { PDSCH-Config } OPTIONAL, -- Need M + sps-Config SetupRelease { SPS-Config } OPTIONAL, -- Need M + radioLinkMonitoringConfig SetupRelease { RadioLinkMonitoringConfig } OPTIONAL, -- Need M + ..., + [[ + sps-ConfigToAddModList-r16 SPS-ConfigToAddModList-r16 OPTIONAL, -- Need N + sps-ConfigToReleaseList-r16 SPS-ConfigToReleaseList-r16 OPTIONAL, -- Need N + sps-ConfigDeactivationStateList-r16 SPS-ConfigDeactivationStateList-r16 OPTIONAL, -- Need R + beamFailureRecoverySCellConfig-r16 SetupRelease {BeamFailureRecoverySCellConfig-r16} OPTIONAL, -- Cond SCellOnly + sl-PDCCH-Config-r16 SetupRelease { PDCCH-Config } OPTIONAL, -- Need M + sl-V2X-PDCCH-Config-r16 SetupRelease { PDCCH-Config } OPTIONAL -- Need M + ]] +} + +SPS-ConfigToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-Config + +SPS-ConfigToReleaseList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-ConfigIndex-r16 + +SPS-ConfigDeactivationState-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-Config-r16)) OF SPS-ConfigIndex-r16 + +SPS-ConfigDeactivationStateList-r16 ::= SEQUENCE (SIZE (1..maxNrofSPS-DeactivationState)) OF SPS-ConfigDeactivationState-r16 + +-- TAG-BWP-DOWNLINKDEDICATED-STOP +-- TAG-BWP-ID-START + +BWP-Id ::= INTEGER (0..maxNrofBWPs) + +-- TAG-BWP-ID-STOP +-- TAG-BWP-UPLINK-START + +BWP-Uplink ::= SEQUENCE { + bwp-Id BWP-Id, + bwp-Common BWP-UplinkCommon OPTIONAL, -- Cond SetupOtherBWP + bwp-Dedicated BWP-UplinkDedicated OPTIONAL, -- Cond SetupOtherBWP + ... +} + +-- TAG-BWP-UPLINK-STOP +-- TAG-BWP-UPLINKCOMMON-START + +BWP-UplinkCommon ::= SEQUENCE { + genericParameters BWP, + rach-ConfigCommon SetupRelease { RACH-ConfigCommon } OPTIONAL, -- Need M + pusch-ConfigCommon SetupRelease { PUSCH-ConfigCommon } OPTIONAL, -- Need M + pucch-ConfigCommon SetupRelease { PUCCH-ConfigCommon } OPTIONAL, -- Need M + ..., + [[ + rach-ConfigCommonIAB-r16 SetupRelease { RACH-ConfigCommon } OPTIONAL, -- Need M + useInterlacePUCCH-PUSCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + msgA-ConfigCommon-r16 SetupRelease { MsgA-ConfigCommon-r16 } OPTIONAL -- Cond SpCellOnly2 + ]] +} + +-- TAG-BWP-UPLINKCOMMON-STOP +-- TAG-BWP-UPLINKDEDICATED-START + +BWP-UplinkDedicated ::= SEQUENCE { + pucch-Config SetupRelease { PUCCH-Config } OPTIONAL, -- Need M + pusch-Config SetupRelease { PUSCH-Config } OPTIONAL, -- Need M + configuredGrantConfig SetupRelease { ConfiguredGrantConfig } OPTIONAL, -- Need M + srs-Config SetupRelease { SRS-Config } OPTIONAL, -- Need M + beamFailureRecoveryConfig SetupRelease { BeamFailureRecoveryConfig } OPTIONAL, -- Cond SpCellOnly + ..., + [[ + sl-PUCCH-Config-r16 SetupRelease { PUCCH-Config } OPTIONAL, -- Need M + cp-ExtensionC2-r16 INTEGER (1..28) OPTIONAL, -- Need R + cp-ExtensionC3-r16 INTEGER (1..28) OPTIONAL, -- Need R + useInterlacePUCCH-PUSCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + pucch-ConfigurationList-r16 SetupRelease { PUCCH-ConfigurationList-r16 } OPTIONAL, -- Need M + lbt-FailureRecoveryConfig-r16 SetupRelease { LBT-FailureRecoveryConfig-r16 } OPTIONAL, -- Need M + configuredGrantConfigToAddModList-r16 ConfiguredGrantConfigToAddModList-r16 OPTIONAL, -- Need N + configuredGrantConfigToReleaseList-r16 ConfiguredGrantConfigToReleaseList-r16 OPTIONAL, -- Need N + configuredGrantConfigType2DeactivationStateList-r16 ConfiguredGrantConfigType2DeactivationStateList-r16 OPTIONAL -- Need R + ]] + +} + +ConfiguredGrantConfigToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfig + +ConfiguredGrantConfigToReleaseList-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfigIndex-r16 + +ConfiguredGrantConfigType2DeactivationState-r16 ::= SEQUENCE (SIZE (1..maxNrofConfiguredGrantConfig-r16)) OF ConfiguredGrantConfigIndex-r16 + +ConfiguredGrantConfigType2DeactivationStateList-r16 ::= + SEQUENCE (SIZE (1..maxNrofCG-Type2DeactivationState)) OF ConfiguredGrantConfigType2DeactivationState-r16 + +-- TAG-BWP-UPLINKDEDICATED-STOP +-- TAG-CELLACCESSRELATEDINFO-START + +CellAccessRelatedInfo ::= SEQUENCE { + plmn-IdentityList PLMN-IdentityInfoList, + cellReservedForOtherUse ENUMERATED {true} OPTIONAL, -- Need R + ..., + [[ + cellReservedForFutureUse-r16 ENUMERATED {true} OPTIONAL, -- Need R + npn-IdentityInfoList-r16 NPN-IdentityInfoList-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-CELLACCESSRELATEDINFO-STOP +-- TAG-CELLACCESSRELATEDINFOEUTRA-5GC-START + +CellAccessRelatedInfo-EUTRA-5GC ::= SEQUENCE { + plmn-IdentityList-eutra-5gc PLMN-IdentityList-EUTRA-5GC, + trackingAreaCode-eutra-5gc TrackingAreaCode, + ranac-5gc RAN-AreaCode OPTIONAL, + cellIdentity-eutra-5gc CellIdentity-EUTRA-5GC +} + +PLMN-IdentityList-EUTRA-5GC::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity-EUTRA-5GC + +PLMN-Identity-EUTRA-5GC ::= CHOICE { + plmn-Identity-EUTRA-5GC PLMN-Identity, + plmn-index INTEGER (1..maxPLMN) +} + +CellIdentity-EUTRA-5GC ::= CHOICE { + cellIdentity-EUTRA BIT STRING (SIZE (28)), + cellId-index INTEGER (1..maxPLMN) +} + +-- TAG-CELLACCESSRELATEDINFOEUTRA-5GC-STOP +-- TAG-CELLACCESSRELATEDINFOEUTRA-EPC-START + +CellAccessRelatedInfo-EUTRA-EPC ::= SEQUENCE { + plmn-IdentityList-eutra-epc PLMN-IdentityList-EUTRA-EPC, + trackingAreaCode-eutra-epc BIT STRING (SIZE (16)), + cellIdentity-eutra-epc BIT STRING (SIZE (28)) +} + +PLMN-IdentityList-EUTRA-EPC::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity + +-- TAG-CELLACCESSRELATEDINFOEUTRA-EPC-STOP +-- TAG-CELLGROUPCONFIG-START + +-- Configuration of one Cell-Group: +CellGroupConfig ::= SEQUENCE { + cellGroupId CellGroupId, + rlc-BearerToAddModList SEQUENCE (SIZE(1..maxLC-ID)) OF RLC-BearerConfig OPTIONAL, -- Need N + rlc-BearerToReleaseList SEQUENCE (SIZE(1..maxLC-ID)) OF LogicalChannelIdentity OPTIONAL, -- Need N + mac-CellGroupConfig MAC-CellGroupConfig OPTIONAL, -- Need M + physicalCellGroupConfig PhysicalCellGroupConfig OPTIONAL, -- Need M + spCellConfig SpCellConfig OPTIONAL, -- Need M + sCellToAddModList SEQUENCE (SIZE (1..maxNrofSCells)) OF SCellConfig OPTIONAL, -- Need N + sCellToReleaseList SEQUENCE (SIZE (1..maxNrofSCells)) OF SCellIndex OPTIONAL, -- Need N + ..., + [[ + reportUplinkTxDirectCurrent ENUMERATED {true} OPTIONAL -- Cond BWP-Reconfig + ]], + [[ + bap-Address-r16 BIT STRING (SIZE (10)) OPTIONAL, -- Need M + bh-RLC-ChannelToAddModList-r16 SEQUENCE (SIZE(1..maxBH-RLC-ChannelID-r16)) OF BH-RLC-ChannelConfig-r16 OPTIONAL, -- Need N + bh-RLC-ChannelToReleaseList-r16 SEQUENCE (SIZE(1..maxBH-RLC-ChannelID-r16)) OF BH-RLC-ChannelID-r16 OPTIONAL, -- Need N + f1c-TransferPath-r16 ENUMERATED {lte, nr, both} OPTIONAL, -- Need M + simultaneousTCI-UpdateList1-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousTCI-UpdateList2-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousSpatial-UpdatedList1-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + simultaneousSpatial-UpdatedList2-r16 SEQUENCE (SIZE (1..maxNrofServingCellsTCI-r16)) OF ServCellIndex OPTIONAL, -- Need R + uplinkTxSwitchingOption-r16 ENUMERATED {switchedUL, dualUL} OPTIONAL, -- Need R + uplinkTxSwitchingPowerBoosting-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]], + [[ + reportUplinkTxDirectCurrentTwoCarrier-r16 ENUMERATED {true} OPTIONAL -- Need N + ]] +} + +-- Serving cell specific MAC and PHY parameters for a SpCell: +SpCellConfig ::= SEQUENCE { + servCellIndex ServCellIndex OPTIONAL, -- Cond SCG + reconfigurationWithSync ReconfigurationWithSync OPTIONAL, -- Cond ReconfWithSync + rlf-TimersAndConstants SetupRelease { RLF-TimersAndConstants } OPTIONAL, -- Need M + rlmInSyncOutOfSyncThreshold ENUMERATED {n1} OPTIONAL, -- Need S + spCellConfigDedicated ServingCellConfig OPTIONAL, -- Need M + ... +} + +ReconfigurationWithSync ::= SEQUENCE { + spCellConfigCommon ServingCellConfigCommon OPTIONAL, -- Need M + newUE-Identity RNTI-Value, + t304 ENUMERATED {ms50, ms100, ms150, ms200, ms500, ms1000, ms2000, ms10000}, + rach-ConfigDedicated CHOICE { + uplink RACH-ConfigDedicated, + supplementaryUplink RACH-ConfigDedicated + } OPTIONAL, -- Need N + ..., + [[ + smtc SSB-MTC OPTIONAL -- Need S + ]], + [[ + daps-UplinkPowerConfig-r16 DAPS-UplinkPowerConfig-r16 OPTIONAL -- Need N + ]] +} + +DAPS-UplinkPowerConfig-r16 ::= SEQUENCE { + p-DAPS-Source-r16 P-Max, + p-DAPS-Target-r16 P-Max, + uplinkPowerSharingDAPS-Mode-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic } +} + +SCellConfig ::= SEQUENCE { + sCellIndex SCellIndex, + sCellConfigCommon ServingCellConfigCommon OPTIONAL, -- Cond SCellAdd + sCellConfigDedicated ServingCellConfig OPTIONAL, -- Cond SCellAddMod + ..., + [[ + smtc SSB-MTC OPTIONAL -- Need S + ]], + [[ + sCellState-r16 ENUMERATED {activated} OPTIONAL, -- Cond SCellAddSync + secondaryDRX-GroupConfig-r16 ENUMERATED {true} OPTIONAL -- Cond DRX-Config2 + ]]} + +-- TAG-CELLGROUPCONFIG-STOP +-- TAG-CELLGROUPID-START + +CellGroupId ::= INTEGER (0.. maxSecondaryCellGroups) + +-- TAG-CELLGROUPID-STOP +-- TAG-CELLIDENTITY-START + +CellIdentity ::= BIT STRING (SIZE (36)) + +-- TAG-CELLIDENTITY-STOP +-- TAG-CELLRESELECTIONPRIORITY-START + +CellReselectionPriority ::= INTEGER (0..7) + +-- TAG-CELLRESELECTIONPRIORITY-STOP +-- TAG-CELLRESELECTIONSUBPRIORITY-START + +CellReselectionSubPriority ::= ENUMERATED {oDot2, oDot4, oDot6, oDot8} + +-- TAG-CELLRESELECTIONSUBPRIORITY-STOP +-- TAG-CGI-INFOEUTRA-START + +CGI-InfoEUTRA ::= SEQUENCE { + cgi-info-EPC SEQUENCE { + cgi-info-EPC-legacy CellAccessRelatedInfo-EUTRA-EPC, + cgi-info-EPC-list SEQUENCE (SIZE (1..maxPLMN)) OF CellAccessRelatedInfo-EUTRA-EPC OPTIONAL + } OPTIONAL, + cgi-info-5GC SEQUENCE (SIZE (1..maxPLMN)) OF CellAccessRelatedInfo-EUTRA-5GC OPTIONAL, + freqBandIndicator FreqBandIndicatorEUTRA, + multiBandInfoList MultiBandInfoListEUTRA OPTIONAL, + freqBandIndicatorPriority ENUMERATED {true} OPTIONAL +} + +-- TAG-CGI-INFOEUTRA-STOP +-- TAG-CGI-INFOEUTRALOGGING-START + +CGI-InfoEUTRALogging ::= SEQUENCE { + plmn-Identity-eutra-5gc PLMN-Identity OPTIONAL, + trackingAreaCode-eutra-5gc TrackingAreaCode OPTIONAL, + cellIdentity-eutra-5gc BIT STRING (SIZE (28)) OPTIONAL, + plmn-Identity-eutra-epc PLMN-Identity OPTIONAL, + trackingAreaCode-eutra-epc BIT STRING (SIZE (16)) OPTIONAL, + cellIdentity-eutra-epc BIT STRING (SIZE (28)) OPTIONAL +} + +-- TAG-CGI-INFOEUTRALOGGING-STOP +-- TAG-CGI-INFO-NR-START + +CGI-InfoNR ::= SEQUENCE { + plmn-IdentityInfoList PLMN-IdentityInfoList OPTIONAL, + frequencyBandList MultiFrequencyBandListNR OPTIONAL, + noSIB1 SEQUENCE { + ssb-SubcarrierOffset INTEGER (0..15), + pdcch-ConfigSIB1 PDCCH-ConfigSIB1 + } OPTIONAL, + ..., + [[ + npn-IdentityInfoList-r16 NPN-IdentityInfoList-r16 OPTIONAL + ]] +} + +-- TAG-CGI-INFO-NR-STOP +-- TAG-CGI-INFO-LOGGING-START + +CGI-Info-Logging-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + cellIdentity-r16 CellIdentity, + trackingAreaCode-r16 TrackingAreaCode OPTIONAL +} + +-- TAG-CGI-INFO-LOGGING-STOP +-- TAG-CLI-RSSI-RANGE-START + +CLI-RSSI-Range-r16 ::= INTEGER(0..76) + +-- TAG-CLI-RSSI-RANGE-STOP +-- TAG-CODEBOOKCONFIG-START + +CodebookConfig ::= SEQUENCE { + codebookType CHOICE { + type1 SEQUENCE { + subType CHOICE { + typeI-SinglePanel SEQUENCE { + nrOfAntennaPorts CHOICE { + two SEQUENCE { + twoTX-CodebookSubsetRestriction BIT STRING (SIZE (6)) + }, + moreThanTwo SEQUENCE { + n1-n2 CHOICE { + two-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (8)), + two-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (64)), + four-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (16)), + three-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (96)), + six-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (24)), + four-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (128)), + eight-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (32)), + four-three-TypeI-SinglePanel-Restriction BIT STRING (SIZE (192)), + six-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (192)), + twelve-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (48)), + four-four-TypeI-SinglePanel-Restriction BIT STRING (SIZE (256)), + eight-two-TypeI-SinglePanel-Restriction BIT STRING (SIZE (256)), + sixteen-one-TypeI-SinglePanel-Restriction BIT STRING (SIZE (64)) + }, + typeI-SinglePanel-codebookSubsetRestriction-i2 BIT STRING (SIZE (16)) OPTIONAL -- Need R + } + }, + typeI-SinglePanel-ri-Restriction BIT STRING (SIZE (8)) + }, + typeI-MultiPanel SEQUENCE { + ng-n1-n2 CHOICE { + two-two-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (8)), + two-four-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (16)), + four-two-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (8)), + two-two-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (64)), + two-eight-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (32)), + four-four-one-TypeI-MultiPanel-Restriction BIT STRING (SIZE (16)), + two-four-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (128)), + four-two-two-TypeI-MultiPanel-Restriction BIT STRING (SIZE (64)) + }, + ri-Restriction BIT STRING (SIZE (4)) + } + }, + codebookMode INTEGER (1..2) + + }, + type2 SEQUENCE { + subType CHOICE { + typeII SEQUENCE { + n1-n2-codebookSubsetRestriction CHOICE { + two-one BIT STRING (SIZE (16)), + two-two BIT STRING (SIZE (43)), + four-one BIT STRING (SIZE (32)), + three-two BIT STRING (SIZE (59)), + six-one BIT STRING (SIZE (48)), + four-two BIT STRING (SIZE (75)), + eight-one BIT STRING (SIZE (64)), + four-three BIT STRING (SIZE (107)), + six-two BIT STRING (SIZE (107)), + twelve-one BIT STRING (SIZE (96)), + four-four BIT STRING (SIZE (139)), + eight-two BIT STRING (SIZE (139)), + sixteen-one BIT STRING (SIZE (128)) + }, + typeII-RI-Restriction BIT STRING (SIZE (2)) + }, + typeII-PortSelection SEQUENCE { + portSelectionSamplingSize ENUMERATED {n1, n2, n3, n4} OPTIONAL, -- Need R + typeII-PortSelectionRI-Restriction BIT STRING (SIZE (2)) + } + }, + phaseAlphabetSize ENUMERATED {n4, n8}, + subbandAmplitude BOOLEAN, + numberOfBeams ENUMERATED {two, three, four} + } + } +} + +CodebookConfig-r16 ::= SEQUENCE { + codebookType CHOICE { + type2 SEQUENCE { + subType CHOICE { + typeII-r16 SEQUENCE { + n1-n2-codebookSubsetRestriction-r16 CHOICE { + two-one BIT STRING (SIZE (16)), + two-two BIT STRING (SIZE (43)), + four-one BIT STRING (SIZE (32)), + three-two BIT STRING (SIZE (59)), + six-one BIT STRING (SIZE (48)), + four-two BIT STRING (SIZE (75)), + eight-one BIT STRING (SIZE (64)), + four-three BIT STRING (SIZE (107)), + six-two BIT STRING (SIZE (107)), + twelve-one BIT STRING (SIZE (96)), + four-four BIT STRING (SIZE (139)), + eight-two BIT STRING (SIZE (139)), + sixteen-one BIT STRING (SIZE (128)) + }, + typeII-RI-Restriction-r16 BIT STRING (SIZE(4)) + }, + typeII-PortSelection-r16 SEQUENCE { + portSelectionSamplingSize-r16 ENUMERATED {n1, n2, n3, n4}, + typeII-PortSelectionRI-Restriction-r16 BIT STRING (SIZE (4)) + } + }, + numberOfPMI-SubbandsPerCQI-Subband-r16 INTEGER (1..2), + paramCombination-r16 INTEGER (1..8) + } + } +} + +-- TAG-CODEBOOKCONFIG-STOP +-- TAG-COMMONLOCATIONINFO-START + +CommonLocationInfo-r16 ::= SEQUENCE { + gnss-TOD-msec-r16 OCTET STRING OPTIONAL, + locationTimestamp-r16 OCTET STRING OPTIONAL, + locationCoordinate-r16 OCTET STRING OPTIONAL, + locationError-r16 OCTET STRING OPTIONAL, + locationSource-r16 OCTET STRING OPTIONAL, + velocityEstimate-r16 OCTET STRING OPTIONAL +} + +-- TAG-COMMONLOCATIONINFO-STOP +-- TAG-CONDRECONFIGID-START + +CondReconfigId-r16 ::= INTEGER (1.. maxNrofCondCells-r16) + +-- TAG-CONDRECONFIGID-STOP +-- TAG-CONDRECONFIGTOADDMODLIST-START + +CondReconfigToAddModList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCondCells-r16)) OF CondReconfigToAddMod-r16 + +CondReconfigToAddMod-r16 ::= SEQUENCE { + condReconfigId-r16 CondReconfigId-r16, + condExecutionCond-r16 SEQUENCE (SIZE (1..2)) OF MeasId OPTIONAL, -- Cond condReconfigAdd + condRRCReconfig-r16 OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, -- Cond condReconfigAdd + ... +} + +-- TAG-CONDRECONFIGTOADDMODLIST-STOP +-- TAG-CONDITIONALRECONFIGURATION-START + +ConditionalReconfiguration-r16 ::= SEQUENCE { + attemptCondReconfig-r16 ENUMERATED {true} OPTIONAL, -- Cond CHO + condReconfigToRemoveList-r16 CondReconfigToRemoveList-r16 OPTIONAL, -- Need N + condReconfigToAddModList-r16 CondReconfigToAddModList-r16 OPTIONAL, -- Need N + ... +} + +CondReconfigToRemoveList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCondCells-r16)) OF CondReconfigId-r16 + +-- TAG-CONDITIONALRECONFIGURATION-STOP +-- TAG-CONFIGUREDGRANTCONFIG-START + +ConfiguredGrantConfig ::= SEQUENCE { + frequencyHopping ENUMERATED {intraSlot, interSlot} OPTIONAL, -- Need S + cg-DMRS-Configuration DMRS-UplinkConfig, + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoder ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + uci-OnPUSCH SetupRelease { CG-UCI-OnPUSCH } OPTIONAL, -- Need M + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch }, + rbg-Size ENUMERATED {config2} OPTIONAL, -- Need S + powerControlLoopToUse ENUMERATED {n0, n1}, + p0-PUSCH-Alpha P0-PUSCH-AlphaSetId, + transformPrecoder ENUMERATED {enabled, disabled} OPTIONAL, -- Need S + nrofHARQ-Processes INTEGER(1..16), + repK ENUMERATED {n1, n2, n4, n8}, + repK-RV ENUMERATED {s1-0231, s2-0303, s3-0000} OPTIONAL, -- Need R + periodicity ENUMERATED { + sym2, sym7, sym1x14, sym2x14, sym4x14, sym5x14, sym8x14, sym10x14, sym16x14, sym20x14, + sym32x14, sym40x14, sym64x14, sym80x14, sym128x14, sym160x14, sym256x14, sym320x14, sym512x14, + sym640x14, sym1024x14, sym1280x14, sym2560x14, sym5120x14, + sym6, sym1x12, sym2x12, sym4x12, sym5x12, sym8x12, sym10x12, sym16x12, sym20x12, sym32x12, + sym40x12, sym64x12, sym80x12, sym128x12, sym160x12, sym256x12, sym320x12, sym512x12, sym640x12, + sym1280x12, sym2560x12 + }, + configuredGrantTimer INTEGER (1..64) OPTIONAL, -- Need R + rrc-ConfiguredUplinkGrant SEQUENCE { + timeDomainOffset INTEGER (0..5119), + timeDomainAllocation INTEGER (0..15), + frequencyDomainAllocation BIT STRING (SIZE(18)), + antennaPort INTEGER (0..31), + dmrs-SeqInitialization INTEGER (0..1) OPTIONAL, -- Need R + precodingAndNumberOfLayers INTEGER (0..63), + srs-ResourceIndicator INTEGER (0..15) OPTIONAL, -- Need R + mcsAndTBS INTEGER (0..31), + frequencyHoppingOffset INTEGER (1.. maxNrofPhysicalResourceBlocks-1) OPTIONAL, -- Need R + pathlossReferenceIndex INTEGER (0..maxNrofPUSCH-PathlossReferenceRSs-1), + ..., + [[ + pusch-RepTypeIndicator-r16 ENUMERATED {pusch-RepTypeA,pusch-RepTypeB} OPTIONAL, -- Need M + frequencyHoppingPUSCH-RepTypeB-r16 ENUMERATED {interRepetition, interSlot} OPTIONAL, -- Cond RepTypeB + timeReferenceSFN-r16 ENUMERATED {sfn512} OPTIONAL -- Need S + ]] + } OPTIONAL, -- Need R + ..., + [[ + cg-RetransmissionTimer-r16 INTEGER (1..64) OPTIONAL, -- Need R + cg-minDFI-Delay-r16 ENUMERATED + {sym7, sym1x14, sym2x14, sym3x14, sym4x14, sym5x14, sym6x14, sym7x14, sym8x14, + sym9x14, sym10x14, sym11x14, sym12x14, sym13x14, sym14x14,sym15x14, sym16x14 + } OPTIONAL, -- Need R + cg-nrofPUSCH-InSlot-r16 INTEGER (1..7) OPTIONAL, -- Need R + cg-nrofSlots-r16 INTEGER (1..40) OPTIONAL, -- Need R + cg-StartingOffsets-r16 CG-StartingOffsets-r16 OPTIONAL, -- Need R + cg-UCI-Multiplexing-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + cg-COT-SharingOffset-r16 INTEGER (1..39) OPTIONAL, -- Need R + betaOffsetCG-UCI-r16 INTEGER (0..31) OPTIONAL, -- Need R + cg-COT-SharingList-r16 SEQUENCE (SIZE (1..1709)) OF CG-COT-Sharing-r16 OPTIONAL, -- Need R + harq-ProcID-Offset-r16 INTEGER (0..15) OPTIONAL, -- Need M + harq-ProcID-Offset2-r16 INTEGER (0..15) OPTIONAL, -- Need M + configuredGrantConfigIndex-r16 ConfiguredGrantConfigIndex-r16 OPTIONAL, -- Cond CG-List + configuredGrantConfigIndexMAC-r16 ConfiguredGrantConfigIndexMAC-r16 OPTIONAL, -- Cond CG-IndexMAC + periodicityExt-r16 INTEGER (1..5120) OPTIONAL, -- Need R + startingFromRV0-r16 ENUMERATED {on, off} OPTIONAL, -- Need R + phy-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL, -- Need R + autonomousTx-r16 ENUMERATED {enabled} OPTIONAL -- Cond LCH-BasedPrioritization + ]] + +} + +CG-UCI-OnPUSCH ::= CHOICE { + dynamic SEQUENCE (SIZE (1..4)) OF BetaOffsets, + semiStatic BetaOffsets +} + +CG-COT-Sharing-r16 ::= CHOICE { + noCOT-Sharing-r16 NULL, + cot-Sharing-r16 SEQUENCE { + duration-r16 INTEGER (1..39), + offset-r16 INTEGER (1..39), + channelAccessPriority-r16 INTEGER (1..4) + } +} + +CG-StartingOffsets-r16 ::= SEQUENCE { + cg-StartingFullBW-InsideCOT-r16 SEQUENCE (SIZE (1..7)) OF INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingFullBW-OutsideCOT-r16 SEQUENCE (SIZE (1..7)) OF INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingPartialBW-InsideCOT-r16 INTEGER (0..6) OPTIONAL, -- Need R + cg-StartingPartialBW-OutsideCOT-r16 INTEGER (0..6) OPTIONAL -- Need R +} + +-- TAG-CONFIGUREDGRANTCONFIG-STOP +-- TAG-CONFIGUREDGRANTCONFIGINDEX-START + +ConfiguredGrantConfigIndex-r16 ::= INTEGER (0.. maxNrofConfiguredGrantConfig-r16-1) + +-- TAG-CONFIGUREDGRANTCONFIGINDEX-STOP +-- TAG-CONFIGUREDGRANTCONFIGINDEXMAC-START + +ConfiguredGrantConfigIndexMAC-r16 ::= INTEGER (0.. maxNrofConfiguredGrantConfigMAC-r16-1) + +-- TAG-CONFIGUREDGRANTCONFIGINDEXMAC-STOP +-- TAG-CONNESTFAILURECONTROL-START + +ConnEstFailureControl ::= SEQUENCE { + connEstFailCount ENUMERATED {n1, n2, n3, n4}, + connEstFailOffsetValidity ENUMERATED {s30, s60, s120, s240, s300, s420, s600, s900}, + connEstFailOffset INTEGER (0..15) OPTIONAL -- Need S +} + +-- TAG-CONNESTFAILURECONTROL-STOP +-- TAG-CONTROLRESOURCESET-START + +ControlResourceSet ::= SEQUENCE { + controlResourceSetId ControlResourceSetId, + + frequencyDomainResources BIT STRING (SIZE (45)), + duration INTEGER (1..maxCoReSetDuration), + cce-REG-MappingType CHOICE { + interleaved SEQUENCE { + reg-BundleSize ENUMERATED {n2, n3, n6}, + interleaverSize ENUMERATED {n2, n3, n6}, + shiftIndex INTEGER(0..maxNrofPhysicalResourceBlocks-1) OPTIONAL -- Need S + }, + nonInterleaved NULL + }, + precoderGranularity ENUMERATED {sameAsREG-bundle, allContiguousRBs}, + tci-StatesPDCCH-ToAddList SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL, -- Cond NotSIB1-initialBWP + tci-StatesPDCCH-ToReleaseList SEQUENCE(SIZE (1..maxNrofTCI-StatesPDCCH)) OF TCI-StateId OPTIONAL, -- Cond NotSIB1-initialBWP + tci-PresentInDCI ENUMERATED {enabled} OPTIONAL, -- Need S + pdcch-DMRS-ScramblingID INTEGER (0..65535) OPTIONAL, -- Need S + ..., + [[ + rb-Offset-r16 INTEGER (0..5) OPTIONAL, -- Need S + tci-PresentDCI-1-2-r16 INTEGER (1..3) OPTIONAL, -- Need S + coresetPoolIndex-r16 INTEGER (0..1) OPTIONAL, -- Need S + controlResourceSetId-v1610 ControlResourceSetId-v1610 OPTIONAL -- Need S + ]] +} + +-- TAG-CONTROLRESOURCESET-STOP +-- TAG-CONTROLRESOURCESETID-START + +ControlResourceSetId ::= INTEGER (0..maxNrofControlResourceSets-1) + +ControlResourceSetId-r16 ::= INTEGER (0..maxNrofControlResourceSets-1-r16) + +ControlResourceSetId-v1610 ::= INTEGER (maxNrofControlResourceSets..maxNrofControlResourceSets-1-r16) + +-- TAG-CONTROLRESOURCESETID-STOP +-- TAG-CONTROLRESOURCESETZERO-START + +ControlResourceSetZero ::= INTEGER (0..15) + +-- TAG-CONTROLRESOURCESETZERO-STOP +-- TAG-CROSSCARRIERSCHEDULINGCONFIG-START + +CrossCarrierSchedulingConfig ::= SEQUENCE { + schedulingCellInfo CHOICE { + own SEQUENCE { -- Cross carrier scheduling: scheduling cell + cif-Presence BOOLEAN + }, + other SEQUENCE { -- Cross carrier scheduling: scheduled cell + schedulingCellId ServCellIndex, + cif-InSchedulingCell INTEGER (1..7) + } + }, + ..., + [[ + carrierIndicatorSize-r16 SEQUENCE { + carrierIndicatorSizeDCI-1-2-r16 INTEGER (0..3), + carrierIndicatorSizeDCI-0-2-r16 INTEGER (0..3) + } OPTIONAL, -- Cond CIF-PRESENCE + enableDefaultBeamForCCS-r16 ENUMERATED {enabled} OPTIONAL -- Need S + ]] +} + +-- TAG-CROSSCARRIERSCHEDULINGCONFIG-STOP +-- TAG-CSI-APERIODICTRIGGERSTATELIST-START + +CSI-AperiodicTriggerStateList ::= SEQUENCE (SIZE (1..maxNrOfCSI-AperiodicTriggers)) OF CSI-AperiodicTriggerState + +CSI-AperiodicTriggerState ::= SEQUENCE { + associatedReportConfigInfoList SEQUENCE (SIZE(1..maxNrofReportConfigPerAperiodicTrigger)) OF CSI-AssociatedReportConfigInfo, + ... +} + +CSI-AssociatedReportConfigInfo ::= SEQUENCE { + reportConfigId CSI-ReportConfigId, + resourcesForChannel CHOICE { + nzp-CSI-RS SEQUENCE { + resourceSet INTEGER (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig), + qcl-info SEQUENCE (SIZE(1..maxNrofAP-CSI-RS-ResourcesPerSet)) OF TCI-StateId + OPTIONAL -- Cond Aperiodic + }, + csi-SSB-ResourceSet INTEGER (1..maxNrofCSI-SSB-ResourceSetsPerConfig) + }, + csi-IM-ResourcesForInterference INTEGER(1..maxNrofCSI-IM-ResourceSetsPerConfig) OPTIONAL, -- Cond CSI-IM-ForInterference + nzp-CSI-RS-ResourcesForInterference INTEGER (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig) OPTIONAL, -- Cond NZP-CSI-RS-ForInterference + ... +} + +-- TAG-CSI-APERIODICTRIGGERSTATELIST-STOP +-- TAG-CSI-FREQUENCYOCCUPATION-START + +CSI-FrequencyOccupation ::= SEQUENCE { + startingRB INTEGER (0..maxNrofPhysicalResourceBlocks-1), + nrofRBs INTEGER (24..maxNrofPhysicalResourceBlocksPlus1), + ... +} + +-- TAG-CSI-FREQUENCYOCCUPATION-STOP +-- TAG-CSI-IM-RESOURCE-START + +CSI-IM-Resource ::= SEQUENCE { + csi-IM-ResourceId CSI-IM-ResourceId, + csi-IM-ResourceElementPattern CHOICE { + pattern0 SEQUENCE { + subcarrierLocation-p0 ENUMERATED { s0, s2, s4, s6, s8, s10 }, + symbolLocation-p0 INTEGER (0..12) + }, + pattern1 SEQUENCE { + subcarrierLocation-p1 ENUMERATED { s0, s4, s8 }, + symbolLocation-p1 INTEGER (0..13) + } + } OPTIONAL, -- Need M + freqBand CSI-FrequencyOccupation OPTIONAL, -- Need M + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, -- Cond PeriodicOrSemiPersistent + ... +} + +-- TAG-CSI-IM-RESOURCE-STOP +-- TAG-CSI-IM-RESOURCEID-START + +CSI-IM-ResourceId ::= INTEGER (0..maxNrofCSI-IM-Resources-1) + +-- TAG-CSI-IM-RESOURCEID-STOP +-- TAG-CSI-IM-RESOURCESET-START + +CSI-IM-ResourceSet ::= SEQUENCE { + csi-IM-ResourceSetId CSI-IM-ResourceSetId, + csi-IM-Resources SEQUENCE (SIZE(1..maxNrofCSI-IM-ResourcesPerSet)) OF CSI-IM-ResourceId, + ... +} +-- TAG-CSI-IM-RESOURCESET-STOP +-- TAG-CSI-IM-RESOURCESETID-START + +CSI-IM-ResourceSetId ::= INTEGER (0..maxNrofCSI-IM-ResourceSets-1) + +-- TAG-CSI-IM-RESOURCESETID-STOP +-- TAG-CSI-MEASCONFIG-START + +CSI-MeasConfig ::= SEQUENCE { + nzp-CSI-RS-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-Resources)) OF NZP-CSI-RS-Resource OPTIONAL, -- Need N + nzp-CSI-RS-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-Resources)) OF NZP-CSI-RS-ResourceId OPTIONAL, -- Need N + nzp-CSI-RS-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSets)) OF NZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + nzp-CSI-RS-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSets)) OF NZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + csi-IM-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofCSI-IM-Resources)) OF CSI-IM-Resource OPTIONAL, -- Need N + csi-IM-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-IM-Resources)) OF CSI-IM-ResourceId OPTIONAL, -- Need N + csi-IM-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSets)) OF CSI-IM-ResourceSet OPTIONAL, -- Need N + csi-IM-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSets)) OF CSI-IM-ResourceSetId OPTIONAL, -- Need N + csi-SSB-ResourceSetToAddModList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSets)) OF CSI-SSB-ResourceSet OPTIONAL, -- Need N + csi-SSB-ResourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSets)) OF CSI-SSB-ResourceSetId OPTIONAL, -- Need N + csi-ResourceConfigToAddModList SEQUENCE (SIZE (1..maxNrofCSI-ResourceConfigurations)) OF CSI-ResourceConfig + OPTIONAL, -- Need N + csi-ResourceConfigToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-ResourceConfigurations)) OF CSI-ResourceConfigId + OPTIONAL, -- Need N + csi-ReportConfigToAddModList SEQUENCE (SIZE (1..maxNrofCSI-ReportConfigurations)) OF CSI-ReportConfig OPTIONAL, -- Need N + csi-ReportConfigToReleaseList SEQUENCE (SIZE (1..maxNrofCSI-ReportConfigurations)) OF CSI-ReportConfigId + OPTIONAL, -- Need N + reportTriggerSize INTEGER (0..6) OPTIONAL, -- Need M + aperiodicTriggerStateList SetupRelease { CSI-AperiodicTriggerStateList } OPTIONAL, -- Need M + semiPersistentOnPUSCH-TriggerStateList SetupRelease { CSI-SemiPersistentOnPUSCH-TriggerStateList } OPTIONAL, -- Need M + ..., + [[ + reportTriggerSizeDCI-0-2-r16 INTEGER (0..6) OPTIONAL -- Need R + ]] +} + +-- TAG-CSI-MEASCONFIG-STOP +-- TAG-CSI-REPORTCONFIG-START + +CSI-ReportConfig ::= SEQUENCE { + reportConfigId CSI-ReportConfigId, + carrier ServCellIndex OPTIONAL, -- Need S + resourcesForChannelMeasurement CSI-ResourceConfigId, + csi-IM-ResourcesForInterference CSI-ResourceConfigId OPTIONAL, -- Need R + nzp-CSI-RS-ResourcesForInterference CSI-ResourceConfigId OPTIONAL, -- Need R + reportConfigType CHOICE { + periodic SEQUENCE { + reportSlotConfig CSI-ReportPeriodicityAndOffset, + pucch-CSI-ResourceList SEQUENCE (SIZE (1..maxNrofBWPs)) OF PUCCH-CSI-Resource + }, + semiPersistentOnPUCCH SEQUENCE { + reportSlotConfig CSI-ReportPeriodicityAndOffset, + pucch-CSI-ResourceList SEQUENCE (SIZE (1..maxNrofBWPs)) OF PUCCH-CSI-Resource + }, + semiPersistentOnPUSCH SEQUENCE { + reportSlotConfig ENUMERATED {sl5, sl10, sl20, sl40, sl80, sl160, sl320}, + reportSlotOffsetList SEQUENCE (SIZE (1.. maxNrofUL-Allocations)) OF INTEGER(0..32), + p0alpha P0-PUSCH-AlphaSetId + }, + aperiodic SEQUENCE { + reportSlotOffsetList SEQUENCE (SIZE (1..maxNrofUL-Allocations)) OF INTEGER(0..32) + } + }, + reportQuantity CHOICE { + none NULL, + cri-RI-PMI-CQI NULL, + cri-RI-i1 NULL, + cri-RI-i1-CQI SEQUENCE { + pdsch-BundleSizeForCSI ENUMERATED {n2, n4} OPTIONAL -- Need S + }, + cri-RI-CQI NULL, + cri-RSRP NULL, + ssb-Index-RSRP NULL, + cri-RI-LI-PMI-CQI NULL + }, + reportFreqConfiguration SEQUENCE { + cqi-FormatIndicator ENUMERATED { widebandCQI, subbandCQI } OPTIONAL, -- Need R + pmi-FormatIndicator ENUMERATED { widebandPMI, subbandPMI } OPTIONAL, -- Need R + csi-ReportingBand CHOICE { + subbands3 BIT STRING(SIZE(3)), + subbands4 BIT STRING(SIZE(4)), + subbands5 BIT STRING(SIZE(5)), + subbands6 BIT STRING(SIZE(6)), + subbands7 BIT STRING(SIZE(7)), + subbands8 BIT STRING(SIZE(8)), + subbands9 BIT STRING(SIZE(9)), + subbands10 BIT STRING(SIZE(10)), + subbands11 BIT STRING(SIZE(11)), + subbands12 BIT STRING(SIZE(12)), + subbands13 BIT STRING(SIZE(13)), + subbands14 BIT STRING(SIZE(14)), + subbands15 BIT STRING(SIZE(15)), + subbands16 BIT STRING(SIZE(16)), + subbands17 BIT STRING(SIZE(17)), + subbands18 BIT STRING(SIZE(18)), + ..., + subbands19-v1530 BIT STRING(SIZE(19)) + } OPTIONAL -- Need S + + } OPTIONAL, -- Need R + timeRestrictionForChannelMeasurements ENUMERATED {configured, notConfigured}, + timeRestrictionForInterferenceMeasurements ENUMERATED {configured, notConfigured}, + codebookConfig CodebookConfig OPTIONAL, -- Need R + dummy ENUMERATED {n1, n2} OPTIONAL, -- Need R + groupBasedBeamReporting CHOICE { + enabled NULL, + disabled SEQUENCE { + nrofReportedRS ENUMERATED {n1, n2, n3, n4} OPTIONAL -- Need S + } + }, + cqi-Table ENUMERATED {table1, table2, table3, spare1} OPTIONAL, -- Need R + subbandSize ENUMERATED {value1, value2}, + non-PMI-PortIndication SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourcesPerConfig)) OF PortIndexFor8Ranks OPTIONAL, -- Need R + ..., + [[ + semiPersistentOnPUSCH-v1530 SEQUENCE { + reportSlotConfig-v1530 ENUMERATED {sl4, sl8, sl16} + } OPTIONAL -- Need R + ]], + [[ + semiPersistentOnPUSCH-v1610 SEQUENCE { + reportSlotOffsetListDCI-0-2-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) OPTIONAL, -- Need R + reportSlotOffsetListDCI-0-1-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) OPTIONAL -- Need R + } OPTIONAL, -- Need R + aperiodic-v1610 SEQUENCE { + reportSlotOffsetListDCI-0-2-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) OPTIONAL, -- Need R + reportSlotOffsetListDCI-0-1-r16 SEQUENCE (SIZE (1.. maxNrofUL-Allocations-r16)) OF INTEGER(0..32) OPTIONAL -- Need R + } OPTIONAL, -- Need R + reportQuantity-r16 CHOICE { + cri-SINR-r16 NULL, + ssb-Index-SINR-r16 NULL + } OPTIONAL, -- Need R + codebookConfig-r16 CodebookConfig-r16 OPTIONAL -- Need R + ]] +} + +CSI-ReportPeriodicityAndOffset ::= CHOICE { + slots4 INTEGER(0..3), + slots5 INTEGER(0..4), + slots8 INTEGER(0..7), + slots10 INTEGER(0..9), + slots16 INTEGER(0..15), + slots20 INTEGER(0..19), + slots40 INTEGER(0..39), + slots80 INTEGER(0..79), + slots160 INTEGER(0..159), + slots320 INTEGER(0..319) +} + +PUCCH-CSI-Resource ::= SEQUENCE { + uplinkBandwidthPartId BWP-Id, + pucch-Resource PUCCH-ResourceId +} + +PortIndexFor8Ranks ::= CHOICE { + portIndex8 SEQUENCE{ + rank1-8 PortIndex8 OPTIONAL, -- Need R + rank2-8 SEQUENCE(SIZE(2)) OF PortIndex8 OPTIONAL, -- Need R + rank3-8 SEQUENCE(SIZE(3)) OF PortIndex8 OPTIONAL, -- Need R + rank4-8 SEQUENCE(SIZE(4)) OF PortIndex8 OPTIONAL, -- Need R + rank5-8 SEQUENCE(SIZE(5)) OF PortIndex8 OPTIONAL, -- Need R + rank6-8 SEQUENCE(SIZE(6)) OF PortIndex8 OPTIONAL, -- Need R + rank7-8 SEQUENCE(SIZE(7)) OF PortIndex8 OPTIONAL, -- Need R + rank8-8 SEQUENCE(SIZE(8)) OF PortIndex8 OPTIONAL -- Need R + }, + portIndex4 SEQUENCE{ + rank1-4 PortIndex4 OPTIONAL, -- Need R + rank2-4 SEQUENCE(SIZE(2)) OF PortIndex4 OPTIONAL, -- Need R + rank3-4 SEQUENCE(SIZE(3)) OF PortIndex4 OPTIONAL, -- Need R + rank4-4 SEQUENCE(SIZE(4)) OF PortIndex4 OPTIONAL -- Need R + }, + portIndex2 SEQUENCE{ + rank1-2 PortIndex2 OPTIONAL, -- Need R + rank2-2 SEQUENCE(SIZE(2)) OF PortIndex2 OPTIONAL -- Need R + }, + portIndex1 NULL +} + +PortIndex8::= INTEGER (0..7) +PortIndex4::= INTEGER (0..3) +PortIndex2::= INTEGER (0..1) + +-- TAG-CSI-REPORTCONFIG-STOP +-- TAG-CSI-REPORTCONFIGID-START + +CSI-ReportConfigId ::= INTEGER (0..maxNrofCSI-ReportConfigurations-1) + +-- TAG-CSI-REPORTCONFIGID-STOP +-- TAG-CSI-RESOURCECONFIG-START + +CSI-ResourceConfig ::= SEQUENCE { + csi-ResourceConfigId CSI-ResourceConfigId, + csi-RS-ResourceSetList CHOICE { + nzp-CSI-RS-SSB SEQUENCE { + nzp-CSI-RS-ResourceSetList SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourceSetsPerConfig)) OF NZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need R + csi-SSB-ResourceSetList SEQUENCE (SIZE (1..maxNrofCSI-SSB-ResourceSetsPerConfig)) OF CSI-SSB-ResourceSetId OPTIONAL -- Need R + }, + csi-IM-ResourceSetList SEQUENCE (SIZE (1..maxNrofCSI-IM-ResourceSetsPerConfig)) OF CSI-IM-ResourceSetId + }, + + bwp-Id BWP-Id, + resourceType ENUMERATED { aperiodic, semiPersistent, periodic }, + ... +} + +-- TAG-CSI-RESOURCECONFIG-STOP +-- TAG-CSI-RESOURCECONFIGID-START + +CSI-ResourceConfigId ::= INTEGER (0..maxNrofCSI-ResourceConfigurations-1) + +-- TAG-CSI-RESOURCECONFIGID-STOP +-- TAG-CSI-RESOURCEPERIODICITYANDOFFSET-START + +CSI-ResourcePeriodicityAndOffset ::= CHOICE { + slots4 INTEGER (0..3), + slots5 INTEGER (0..4), + slots8 INTEGER (0..7), + slots10 INTEGER (0..9), + slots16 INTEGER (0..15), + slots20 INTEGER (0..19), + slots32 INTEGER (0..31), + slots40 INTEGER (0..39), + slots64 INTEGER (0..63), + slots80 INTEGER (0..79), + slots160 INTEGER (0..159), + slots320 INTEGER (0..319), + slots640 INTEGER (0..639) +} + +-- TAG-CSI-RESOURCEPERIODICITYANDOFFSET-STOP +-- TAG-CSI-RS-RESOURCECONFIGMOBILITY-START + +CSI-RS-ResourceConfigMobility ::= SEQUENCE { + subcarrierSpacing SubcarrierSpacing, + csi-RS-CellList-Mobility SEQUENCE (SIZE (1..maxNrofCSI-RS-CellsRRM)) OF CSI-RS-CellMobility, + ..., + [[ + refServCellIndex ServCellIndex OPTIONAL -- Need S + ]] + + +} + +CSI-RS-CellMobility ::= SEQUENCE { + cellId PhysCellId, + csi-rs-MeasurementBW SEQUENCE { + nrofPRBs ENUMERATED { size24, size48, size96, size192, size264}, + startPRB INTEGER(0..2169) + }, + density ENUMERATED {d1,d3} OPTIONAL, -- Need R + csi-rs-ResourceList-Mobility SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesRRM)) OF CSI-RS-Resource-Mobility +} + +CSI-RS-Resource-Mobility ::= SEQUENCE { + csi-RS-Index CSI-RS-Index, + slotConfig CHOICE { + ms4 INTEGER (0..31), + ms5 INTEGER (0..39), + ms10 INTEGER (0..79), + ms20 INTEGER (0..159), + ms40 INTEGER (0..319) + }, + associatedSSB SEQUENCE { + ssb-Index SSB-Index, + isQuasiColocated BOOLEAN + } OPTIONAL, -- Need R + frequencyDomainAllocation CHOICE { + row1 BIT STRING (SIZE (4)), + row2 BIT STRING (SIZE (12)) + }, + firstOFDMSymbolInTimeDomain INTEGER (0..13), + sequenceGenerationConfig INTEGER (0..1023), + ... +} + +CSI-RS-Index ::= INTEGER (0..maxNrofCSI-RS-ResourcesRRM-1) + +-- TAG-CSI-RS-RESOURCECONFIGMOBILITY-STOP +-- TAG-CSI-RS-RESOURCEMAPPING-START + +CSI-RS-ResourceMapping ::= SEQUENCE { + frequencyDomainAllocation CHOICE { + row1 BIT STRING (SIZE (4)), + row2 BIT STRING (SIZE (12)), + row4 BIT STRING (SIZE (3)), + other BIT STRING (SIZE (6)) + }, + nrofPorts ENUMERATED {p1,p2,p4,p8,p12,p16,p24,p32}, + firstOFDMSymbolInTimeDomain INTEGER (0..13), + firstOFDMSymbolInTimeDomain2 INTEGER (2..12) OPTIONAL, -- Need R + cdm-Type ENUMERATED {noCDM, fd-CDM2, cdm4-FD2-TD2, cdm8-FD2-TD4}, + density CHOICE { + dot5 ENUMERATED {evenPRBs, oddPRBs}, + one NULL, + three NULL, + spare NULL + }, + freqBand CSI-FrequencyOccupation, + ... +} + +-- TAG-CSI-RS-RESOURCEMAPPING-STOP +-- TAG-CSI-SEMIPERSISTENTONPUSCHTRIGGERSTATELIST-START + +CSI-SemiPersistentOnPUSCH-TriggerStateList ::= SEQUENCE(SIZE (1..maxNrOfSemiPersistentPUSCH-Triggers)) OF CSI-SemiPersistentOnPUSCH-TriggerState + +CSI-SemiPersistentOnPUSCH-TriggerState ::= SEQUENCE { + associatedReportConfigInfo CSI-ReportConfigId, + ... +} + +-- TAG-CSI-SEMIPERSISTENTONPUSCHTRIGGERSTATELIST-STOP +-- TAG-CSI-SSB-RESOURCESET-START + +CSI-SSB-ResourceSet ::= SEQUENCE { + csi-SSB-ResourceSetId CSI-SSB-ResourceSetId, + csi-SSB-ResourceList SEQUENCE (SIZE(1..maxNrofCSI-SSB-ResourcePerSet)) OF SSB-Index, + ... +} + +-- TAG-CSI-SSB-RESOURCESET-STOP +-- TAG-CSI-SSB-RESOURCESETID-START + +CSI-SSB-ResourceSetId ::= INTEGER (0..maxNrofCSI-SSB-ResourceSets-1) + +-- TAG-CSI-SSB-RESOURCESETID-STOP +-- TAG-DEDICATED-NAS-MESSAGE-START + +DedicatedNAS-Message ::= OCTET STRING + +-- TAG-DEDICATED-NAS-MESSAGE-STOP +-- TAG-DMRS-DOWNLINKCONFIG-START + +DMRS-DownlinkConfig ::= SEQUENCE { + dmrs-Type ENUMERATED {type2} OPTIONAL, -- Need S + dmrs-AdditionalPosition ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + maxLength ENUMERATED {len2} OPTIONAL, -- Need S + scramblingID0 INTEGER (0..65535) OPTIONAL, -- Need S + scramblingID1 INTEGER (0..65535) OPTIONAL, -- Need S + phaseTrackingRS SetupRelease { PTRS-DownlinkConfig } OPTIONAL, -- Need M + ..., + [[ + dmrs-Downlink-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + +} + +-- TAG-DMRS-DOWNLINKCONFIG-STOP +-- TAG-DMRS-UPLINKCONFIG-START + +DMRS-UplinkConfig ::= SEQUENCE { + dmrs-Type ENUMERATED {type2} OPTIONAL, -- Need S + dmrs-AdditionalPosition ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + phaseTrackingRS SetupRelease { PTRS-UplinkConfig } OPTIONAL, -- Need M + maxLength ENUMERATED {len2} OPTIONAL, -- Need S + transformPrecodingDisabled SEQUENCE { + scramblingID0 INTEGER (0..65535) OPTIONAL, -- Need S + scramblingID1 INTEGER (0..65535) OPTIONAL, -- Need S + ..., + [[ + dmrs-Uplink-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + } OPTIONAL, -- Need R + transformPrecodingEnabled SEQUENCE { + nPUSCH-Identity INTEGER(0..1007) OPTIONAL, -- Need S + sequenceGroupHopping ENUMERATED {disabled} OPTIONAL, -- Need S + sequenceHopping ENUMERATED {enabled} OPTIONAL, -- Need S + ..., + [[ + dmrs-UplinkTransformPrecoding-r16 SetupRelease {DMRS-UplinkTransformPrecoding-r16} OPTIONAL -- Need M + ]] + } OPTIONAL, -- Need R + ... +} + +DMRS-UplinkTransformPrecoding-r16 ::= SEQUENCE { + pi2BPSK-ScramblingID0 INTEGER(0..65535) OPTIONAL, -- Need S + pi2BPSK-ScramblingID1 INTEGER(0..65535) OPTIONAL -- Need S +} + +-- TAG-DMRS-UPLINKCONFIG-STOP +-- TAG-DOWNLINKCONFIGCOMMON-START + +DownlinkConfigCommon ::= SEQUENCE { + frequencyInfoDL FrequencyInfoDL OPTIONAL, -- Cond InterFreqHOAndServCellAdd + initialDownlinkBWP BWP-DownlinkCommon OPTIONAL, -- Cond ServCellAdd + ... +} + +-- TAG-DOWNLINKCONFIGCOMMON-STOP +-- TAG-DOWNLINKCONFIGCOMMONSIB-START + +DownlinkConfigCommonSIB ::= SEQUENCE { + frequencyInfoDL FrequencyInfoDL-SIB, + initialDownlinkBWP BWP-DownlinkCommon, + bcch-Config BCCH-Config, + pcch-Config PCCH-Config, + ... +} + + +BCCH-Config ::= SEQUENCE { + modificationPeriodCoeff ENUMERATED {n2, n4, n8, n16}, + ... +} + + +PCCH-Config ::= SEQUENCE { + defaultPagingCycle PagingCycle, + nAndPagingFrameOffset CHOICE { + oneT NULL, + halfT INTEGER (0..1), + quarterT INTEGER (0..3), + oneEighthT INTEGER (0..7), + oneSixteenthT INTEGER (0..15) + }, + ns ENUMERATED {four, two, one}, + firstPDCCH-MonitoringOccasionOfPO CHOICE { + sCS15KHZoneT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..139), + sCS30KHZoneT-SCS15KHZhalfT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..279), + sCS60KHZoneT-SCS30KHZhalfT-SCS15KHZquarterT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..559), + sCS120KHZoneT-SCS60KHZhalfT-SCS30KHZquarterT-SCS15KHZoneEighthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..1119), + sCS120KHZhalfT-SCS60KHZquarterT-SCS30KHZoneEighthT-SCS15KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..2239), + sCS120KHZquarterT-SCS60KHZoneEighthT-SCS30KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..4479), + sCS120KHZoneEighthT-SCS60KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..8959), + sCS120KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..17919) + } OPTIONAL, -- Need R + ..., + [[ + nrofPDCCH-MonitoringOccasionPerSSB-InPO-r16 INTEGER (2..4) OPTIONAL -- Cond SharedSpectrum2 + ]] +} + +-- TAG-DOWNLINKCONFIGCOMMONSIB-STOP +-- TAG-DOWNLINKPREEMPTION-START + +DownlinkPreemption ::= SEQUENCE { + int-RNTI RNTI-Value, + timeFrequencySet ENUMERATED {set0, set1}, + dci-PayloadSize INTEGER (0..maxINT-DCI-PayloadSize), + int-ConfigurationPerServingCell SEQUENCE (SIZE (1..maxNrofServingCells)) OF INT-ConfigurationPerServingCell, + ... +} + +INT-ConfigurationPerServingCell ::= SEQUENCE { + servingCellId ServCellIndex, + positionInDCI INTEGER (0..maxINT-DCI-PayloadSize-1) +} + +-- TAG-DOWNLINKPREEMPTION-STOP +-- TAG-DRB-IDENTITY-START + +DRB-Identity ::= INTEGER (1..32) + +-- TAG-DRB-IDENTITY-STOP +-- TAG-DRX-CONFIG-START + +DRX-Config ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + }, + drx-InactivityTimer ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1}, + drx-HARQ-RTT-TimerDL INTEGER (0..56), + drx-HARQ-RTT-TimerUL INTEGER (0..56), + drx-RetransmissionTimerDL ENUMERATED { + sl0, sl1, sl2, sl4, sl6, sl8, sl16, sl24, sl33, sl40, sl64, sl80, sl96, sl112, sl128, + sl160, sl320, spare15, spare14, spare13, spare12, spare11, spare10, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1}, + drx-RetransmissionTimerUL ENUMERATED { + sl0, sl1, sl2, sl4, sl6, sl8, sl16, sl24, sl33, sl40, sl64, sl80, sl96, sl112, sl128, + sl160, sl320, spare15, spare14, spare13, spare12, spare11, spare10, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-LongCycleStartOffset CHOICE { + ms10 INTEGER(0..9), + ms20 INTEGER(0..19), + ms32 INTEGER(0..31), + ms40 INTEGER(0..39), + ms60 INTEGER(0..59), + ms64 INTEGER(0..63), + ms70 INTEGER(0..69), + ms80 INTEGER(0..79), + ms128 INTEGER(0..127), + ms160 INTEGER(0..159), + ms256 INTEGER(0..255), + ms320 INTEGER(0..319), + ms512 INTEGER(0..511), + ms640 INTEGER(0..639), + ms1024 INTEGER(0..1023), + ms1280 INTEGER(0..1279), + ms2048 INTEGER(0..2047), + ms2560 INTEGER(0..2559), + ms5120 INTEGER(0..5119), + ms10240 INTEGER(0..10239) + }, + shortDRX SEQUENCE { + drx-ShortCycle ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-ShortCycleTimer INTEGER (1..16) + } OPTIONAL, -- Need R + drx-SlotOffset INTEGER (0..31) +} + +-- TAG-DRX-CONFIG-STOP +-- TAG-DRX-CONFIGSECONDARYGROUP-START + +DRX-ConfigSecondaryGroup ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + }, + drx-InactivityTimer ENUMERATED { + ms0, ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, ms80, + ms100, ms200, ms300, ms500, ms750, ms1280, ms1920, ms2560, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1} +} + +-- TAG-DRX-CONFIGSECONDARYGROUP-STOP +-- TAG-FILTERCOEFFICIENT-START + +FilterCoefficient ::= ENUMERATED { fc0, fc1, fc2, fc3, fc4, fc5, fc6, fc7, fc8, fc9, fc11, fc13, fc15, fc17, fc19, spare1, ...} + +-- TAG-FILTERCOEFFICIENT-STOP +-- TAG-FREQBANDINDICATORNR-START + +FreqBandIndicatorNR ::= INTEGER (1..1024) + +-- TAG-FREQBANDINDICATORNR-STOP +-- TAG-FREQUENCYINFODL-START + +FrequencyInfoDL ::= SEQUENCE { + absoluteFrequencySSB ARFCN-ValueNR OPTIONAL, -- Cond SpCellAdd + frequencyBandList MultiFrequencyBandListNR, + absoluteFrequencyPointA ARFCN-ValueNR, + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + ... +} + +-- TAG-FREQUENCYINFODL-STOP +-- TAG-FREQUENCYINFODL-SIB-START + +FrequencyInfoDL-SIB ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR-SIB, + offsetToPointA INTEGER (0..2199), + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier +} + +-- TAG-FREQUENCYINFODL-SIB-STOP +-- TAG-FREQUENCYINFOUL-START + +FrequencyInfoUL ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR OPTIONAL, -- Cond FDD-OrSUL + absoluteFrequencyPointA ARFCN-ValueNR OPTIONAL, -- Cond FDD-OrSUL + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + additionalSpectrumEmission AdditionalSpectrumEmission OPTIONAL, -- Need S + p-Max P-Max OPTIONAL, -- Need S + frequencyShift7p5khz ENUMERATED {true} OPTIONAL, -- Cond FDD-TDD-OrSUL-Optional + ... +} + +-- TAG-FREQUENCYINFOUL-STOP +-- TAG-FREQUENCYINFOUL-SIB-START + +FrequencyInfoUL-SIB ::= SEQUENCE { + frequencyBandList MultiFrequencyBandListNR-SIB OPTIONAL, -- Cond FDD-OrSUL + absoluteFrequencyPointA ARFCN-ValueNR OPTIONAL, -- Cond FDD-OrSUL + scs-SpecificCarrierList SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + p-Max P-Max OPTIONAL, -- Need S + frequencyShift7p5khz ENUMERATED {true} OPTIONAL, -- Cond FDD-TDD-OrSUL-Optional + ... +} + +-- TAG-FREQUENCYINFOUL-SIB-STOP +-- TAG-HIGHSPEEDCONFIG-START + +HighSpeedConfig-r16 ::= SEQUENCE { + highSpeedMeasFlag-r16 ENUMERATED {true} OPTIONAL, -- Need R + highSpeedDemodFlag-r16 ENUMERATED {true} OPTIONAL, -- Need R + ... +} + +-- TAG-HIGHSPEEDCONFIG-STOP +-- TAG-HYSTERESIS-START + +Hysteresis ::= INTEGER (0..30) + +-- TAG-HYSTERESIS-STOP +-- TAG-INVALIDSYMBOLPATTERN-START + +InvalidSymbolPattern-r16 ::= SEQUENCE { + symbols-r16 CHOICE { + oneSlot BIT STRING (SIZE (14)), + twoSlots BIT STRING (SIZE (28)) + }, + periodicityAndPattern-r16 CHOICE { + n2 BIT STRING (SIZE (2)), + n4 BIT STRING (SIZE (4)), + n5 BIT STRING (SIZE (5)), + n8 BIT STRING (SIZE (8)), + n10 BIT STRING (SIZE (10)), + n20 BIT STRING (SIZE (20)), + n40 BIT STRING (SIZE (40)) + } OPTIONAL, -- Need M + ... +} + +-- TAG-INVALIDSYMBOLPATTERN-STOP +-- TAG-I-RNTI-VALUE-START + +I-RNTI-Value ::= BIT STRING (SIZE(40)) + +-- TAG-I-RNTI-VALUE-STOP +-- TAG-LBT-FAILURERECOVERYCONFIG-START + +LBT-FailureRecoveryConfig-r16 ::= SEQUENCE { + lbt-FailureInstanceMaxCount-r16 ENUMERATED {n4, n8, n16, n32, n64, n128}, + lbt-FailureDetectionTimer-r16 ENUMERATED {ms10, ms20, ms40, ms80, ms160, ms320}, + ... +} + +-- TAG-LBT-FAILURERECOVERYCONFIG-STOP +-- TAG-LOCATIONINFO-START + +LocationInfo-r16 ::= SEQUENCE { + commonLocationInfo-r16 CommonLocationInfo-r16 OPTIONAL, + bt-LocationInfo-r16 LogMeasResultListBT-r16 OPTIONAL, + wlan-LocationInfo-r16 LogMeasResultListWLAN-r16 OPTIONAL, + sensor-LocationInfo-r16 Sensor-LocationInfo-r16 OPTIONAL, + ... +} + +-- TAG-LOCATIONINFO-STOP +-- TAG-LOCATIONMEASUREMENTINFO-START + +LocationMeasurementInfo ::= CHOICE { + eutra-RSTD EUTRA-RSTD-InfoList, + ..., + eutra-FineTimingDetection NULL, + nr-PRS-Measurement-r16 NR-PRS-MeasurementInfoList-r16 +} + +EUTRA-RSTD-InfoList ::= SEQUENCE (SIZE (1..maxInterRAT-RSTD-Freq)) OF EUTRA-RSTD-Info + +EUTRA-RSTD-Info ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + measPRS-Offset INTEGER (0..39), + ... +} + +NR-PRS-MeasurementInfoList-r16 ::= SEQUENCE (SIZE (1..maxFreqLayers)) OF NR-PRS-MeasurementInfo-r16 + +NR-PRS-MeasurementInfo-r16 ::= SEQUENCE { + dl-PRS-PointA-r16 ARFCN-ValueNR, + nr-MeasPRS-RepetitionAndOffset-r16 CHOICE { + ms20-r16 INTEGER (0..19), + ms40-r16 INTEGER (0..39), + ms80-r16 INTEGER (0..79), + ms160-r16 INTEGER (0..159), + ... + }, + nr-MeasPRS-length-r16 ENUMERATED {ms1dot5, ms3, ms3dot5, ms4, ms5dot5, ms6, ms10, ms20}, + ... +} + +-- TAG-LOCATIONMEASUREMENTINFO-STOP +-- TAG-LOGICALCHANNELCONFIG-START + +LogicalChannelConfig ::= SEQUENCE { + ul-SpecificParameters SEQUENCE { + priority INTEGER (1..16), + prioritisedBitRate ENUMERATED {kBps0, kBps8, kBps16, kBps32, kBps64, kBps128, kBps256, kBps512, + kBps1024, kBps2048, kBps4096, kBps8192, kBps16384, kBps32768, kBps65536, infinity}, + bucketSizeDuration ENUMERATED {ms5, ms10, ms20, ms50, ms100, ms150, ms300, ms500, ms1000, + spare7, spare6, spare5, spare4, spare3,spare2, spare1}, + allowedServingCells SEQUENCE (SIZE (1..maxNrofServingCells-1)) OF ServCellIndex + OPTIONAL, -- Cond PDCP-CADuplication + allowedSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SubcarrierSpacing OPTIONAL, -- Need R + maxPUSCH-Duration ENUMERATED {ms0p02, ms0p04, ms0p0625, ms0p125, ms0p25, ms0p5, spare2, spare1} + OPTIONAL, -- Need R + configuredGrantType1Allowed ENUMERATED {true} OPTIONAL, -- Need R + logicalChannelGroup INTEGER (0..maxLCG-ID) OPTIONAL, -- Need R + schedulingRequestID SchedulingRequestId OPTIONAL, -- Need R + logicalChannelSR-Mask BOOLEAN, + logicalChannelSR-DelayTimerApplied BOOLEAN, + ..., + bitRateQueryProhibitTimer ENUMERATED {s0, s0dot4, s0dot8, s1dot6, s3, s6, s12, s30} OPTIONAL, -- Need R + [[ + allowedCG-List-r16 SEQUENCE (SIZE (0.. maxNrofConfiguredGrantConfigMAC-r16-1)) OF ConfiguredGrantConfigIndexMAC-r16 + OPTIONAL, -- Need S + allowedPHY-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL -- Need S + ]] + } OPTIONAL, -- Cond UL + ..., + [[ + channelAccessPriority-r16 INTEGER (1..4) OPTIONAL, -- Need R + bitRateMultiplier-r16 ENUMERATED {x40, x70, x100, x200} OPTIONAL -- Need R + ]] +} + +-- TAG-LOGICALCHANNELCONFIG-STOP +-- TAG-LOGICALCHANNELIDENTITY-START + +LogicalChannelIdentity ::= INTEGER (1..maxLC-ID) + +-- TAG-LOGICALCHANNELIDENTITY-STOP +-- TAG-MAC-CELLGROUPCONFIG-START + +MAC-CellGroupConfig ::= SEQUENCE { + drx-Config SetupRelease { DRX-Config } OPTIONAL, -- Need M + schedulingRequestConfig SchedulingRequestConfig OPTIONAL, -- Need M + bsr-Config BSR-Config OPTIONAL, -- Need M + tag-Config TAG-Config OPTIONAL, -- Need M + phr-Config SetupRelease { PHR-Config } OPTIONAL, -- Need M + skipUplinkTxDynamic BOOLEAN, + ..., + [[ + csi-Mask BOOLEAN OPTIONAL, -- Need M + dataInactivityTimer SetupRelease { DataInactivityTimer } OPTIONAL -- Cond MCG-Only + ]], + [[ + usePreBSR-r16 ENUMERATED {true} OPTIONAL, -- Need R + schedulingRequestID-LBT-SCell-r16 SchedulingRequestId OPTIONAL, -- Need R + lch-BasedPrioritization-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + schedulingRequestID-BFR-SCell-r16 SchedulingRequestId OPTIONAL, -- Need R + drx-ConfigSecondaryGroup-r16 SetupRelease { DRX-ConfigSecondaryGroup } OPTIONAL -- Need M + ]], + [[ + enhancedSkipUplinkTxDynamic-r16 ENUMERATED {true} OPTIONAL, -- Need R + enhancedSkipUplinkTxConfigured-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +DataInactivityTimer ::= ENUMERATED {s1, s2, s3, s5, s7, s10, s15, s20, s40, s50, s60, s80, s100, s120, s150, s180} + +-- TAG-MAC-CELLGROUPCONFIG-STOP +-- TAG-MEASCONFIG-START + +MeasConfig ::= SEQUENCE { + measObjectToRemoveList MeasObjectToRemoveList OPTIONAL, -- Need N + measObjectToAddModList MeasObjectToAddModList OPTIONAL, -- Need N + reportConfigToRemoveList ReportConfigToRemoveList OPTIONAL, -- Need N + reportConfigToAddModList ReportConfigToAddModList OPTIONAL, -- Need N + measIdToRemoveList MeasIdToRemoveList OPTIONAL, -- Need N + measIdToAddModList MeasIdToAddModList OPTIONAL, -- Need N + s-MeasureConfig CHOICE { + ssb-RSRP RSRP-Range, + csi-RSRP RSRP-Range + } OPTIONAL, -- Need M + quantityConfig QuantityConfig OPTIONAL, -- Need M + measGapConfig MeasGapConfig OPTIONAL, -- Need M + measGapSharingConfig MeasGapSharingConfig OPTIONAL, -- Need M + ..., + [[ + interFrequencyConfig-NoGap-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +MeasObjectToRemoveList ::= SEQUENCE (SIZE (1..maxNrofObjectId)) OF MeasObjectId + +MeasIdToRemoveList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF MeasId + +ReportConfigToRemoveList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigId + +-- TAG-MEASCONFIG-STOP +-- TAG-MEASGAPCONFIG-START + +MeasGapConfig ::= SEQUENCE { + gapFR2 SetupRelease { GapConfig } OPTIONAL, -- Need M + ..., + [[ + gapFR1 SetupRelease { GapConfig } OPTIONAL, -- Need M + gapUE SetupRelease { GapConfig } OPTIONAL -- Need M + ]] + +} + +GapConfig ::= SEQUENCE { + gapOffset INTEGER (0..159), + mgl ENUMERATED {ms1dot5, ms3, ms3dot5, ms4, ms5dot5, ms6}, + mgrp ENUMERATED {ms20, ms40, ms80, ms160}, + mgta ENUMERATED {ms0, ms0dot25, ms0dot5}, + ..., + [[ + refServCellIndicator ENUMERATED {pCell, pSCell, mcg-FR2} OPTIONAL -- Cond NEDCorNRDC + ]], + [[ + refFR2ServCellAsyncCA-r16 ServCellIndex OPTIONAL, -- Cond AsyncCA + mgl-r16 ENUMERATED {ms10, ms20} OPTIONAL -- Cond PRS + ]] +} + +-- TAG-MEASGAPCONFIG-STOP +-- TAG-MEASGAPSHARINGCONFIG-START + +MeasGapSharingConfig ::= SEQUENCE { + gapSharingFR2 SetupRelease { MeasGapSharingScheme } OPTIONAL, -- Need M + ..., + [[ + gapSharingFR1 SetupRelease { MeasGapSharingScheme } OPTIONAL, --Need M + gapSharingUE SetupRelease { MeasGapSharingScheme } OPTIONAL --Need M + ]] +} + +MeasGapSharingScheme::= ENUMERATED {scheme00, scheme01, scheme10, scheme11} + +-- TAG-MEASGAPSHARINGCONFIG-STOP +-- TAG-MEASID-START + +MeasId ::= INTEGER (1..maxNrofMeasId) + +-- TAG-MEASID-STOP +-- TAG-MEASIDLECONFIG-START + +MeasIdleConfigSIB-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, -- Need S + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, -- Need S + ... +} + +MeasIdleConfigDedicated-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, -- Need N + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, -- Need N + measIdleDuration-r16 ENUMERATED{sec10, sec30, sec60, sec120, sec180, sec240, sec300, spare}, + validityAreaList-r16 ValidityAreaList-r16 OPTIONAL, -- Need N + ... +} + +ValidityAreaList-r16 ::= SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF ValidityArea-r16 + +ValidityArea-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + validityCellList-r16 ValidityCellList OPTIONAL -- Need N +} + +ValidityCellList ::= SEQUENCE (SIZE (1.. maxCellMeasIdle-r16)) OF PCI-Range + +MeasIdleCarrierNR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + ssbSubcarrierSpacing-r16 SubcarrierSpacing, + frequencyBandList MultiFrequencyBandListNR OPTIONAL, -- Need R + measCellListNR-r16 CellListNR-r16 OPTIONAL, -- Need R + reportQuantities-r16 ENUMERATED {rsrp, rsrq, both}, + qualityThreshold-r16 SEQUENCE { + idleRSRP-Threshold-NR-r16 RSRP-Range OPTIONAL, -- Need R + idleRSRQ-Threshold-NR-r16 RSRQ-Range OPTIONAL -- Need R + } OPTIONAL, -- Need R + ssb-MeasConfig-r16 SEQUENCE { + nrofSS-BlocksToAverage-r16 INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need S + absThreshSS-BlocksConsolidation-r16 ThresholdNR OPTIONAL, -- Need S + smtc-r16 SSB-MTC OPTIONAL, -- Need S + ssb-ToMeasure-r16 SSB-ToMeasure OPTIONAL, -- Need S + deriveSSB-IndexFromCell-r16 BOOLEAN, + ss-RSSI-Measurement-r16 SS-RSSI-Measurement OPTIONAL -- Need S + } OPTIONAL, -- Need S + beamMeasConfigIdle-r16 BeamMeasConfigIdle-NR-r16 OPTIONAL, -- Need R + ... +} + +MeasIdleCarrierEUTRA-r16 ::= SEQUENCE { + carrierFreqEUTRA-r16 ARFCN-ValueEUTRA, + allowedMeasBandwidth-r16 EUTRA-AllowedMeasBandwidth, + measCellListEUTRA-r16 CellListEUTRA-r16 OPTIONAL, -- Need R + reportQuantitiesEUTRA-r16 ENUMERATED {rsrp, rsrq, both}, + qualityThresholdEUTRA-r16 SEQUENCE { + idleRSRP-Threshold-EUTRA-r16 RSRP-RangeEUTRA OPTIONAL, -- Need R + idleRSRQ-Threshold-EUTRA-r16 RSRQ-RangeEUTRA-r16 OPTIONAL -- Need R + } OPTIONAL, -- Need S + ... +} + +CellListNR-r16 ::= SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF PCI-Range + +CellListEUTRA-r16 ::= SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF EUTRA-PhysCellIdRange + +BeamMeasConfigIdle-NR-r16 ::= SEQUENCE { + reportQuantityRS-Indexes-r16 ENUMERATED {rsrp, rsrq, both}, + maxNrofRS-IndexesToReport-r16 INTEGER (1.. maxNrofIndexesToReport), + includeBeamMeasurements-r16 BOOLEAN +} + +RSRQ-RangeEUTRA-r16 ::= INTEGER (-30..46) + +-- TAG-MEASIDLECONFIG-STOP +-- TAG-MEASIDTOADDMODLIST-START + +MeasIdToAddModList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF MeasIdToAddMod + +MeasIdToAddMod ::= SEQUENCE { + measId MeasId, + measObjectId MeasObjectId, + reportConfigId ReportConfigId +} + +-- TAG-MEASIDTOADDMODLIST-STOP +-- TAG-MEASOBJECTCLI-START + +MeasObjectCLI-r16 ::= SEQUENCE { + cli-ResourceConfig-r16 CLI-ResourceConfig-r16, + ... +} + +CLI-ResourceConfig-r16 ::= SEQUENCE { + srs-ResourceConfig-r16 SetupRelease { SRS-ResourceListConfigCLI-r16 } OPTIONAL, -- Need M + rssi-ResourceConfig-r16 SetupRelease { RSSI-ResourceListConfigCLI-r16 } OPTIONAL -- Need M +} + +SRS-ResourceListConfigCLI-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-SRS-Resources-r16)) OF SRS-ResourceConfigCLI-r16 + +RSSI-ResourceListConfigCLI-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-RSSI-Resources-r16)) OF RSSI-ResourceConfigCLI-r16 + +SRS-ResourceConfigCLI-r16 ::= SEQUENCE { + srs-Resource-r16 SRS-Resource, + srs-SCS-r16 SubcarrierSpacing, + refServCellIndex-r16 ServCellIndex OPTIONAL, -- Need S + refBWP-r16 BWP-Id, + ... +} + +RSSI-ResourceConfigCLI-r16 ::= SEQUENCE { + rssi-ResourceId-r16 RSSI-ResourceId-r16, + rssi-SCS-r16 SubcarrierSpacing, + startPRB-r16 INTEGER (0..2169), + nrofPRBs-r16 INTEGER (4..maxNrofPhysicalResourceBlocksPlus1), + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 INTEGER (1..14), + rssi-PeriodicityAndOffset-r16 RSSI-PeriodicityAndOffset-r16, + refServCellIndex-r16 ServCellIndex OPTIONAL, -- Need S + ... +} + +RSSI-ResourceId-r16 ::= INTEGER (0.. maxNrofCLI-RSSI-Resources-r16-1) + +RSSI-PeriodicityAndOffset-r16 ::= CHOICE { + sl10 INTEGER(0..9), + sl20 INTEGER(0..19), + sl40 INTEGER(0..39), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + s1640 INTEGER(0..639), + ... +} + +-- TAG-MEASOBJECTCLI-STOP +-- TAG-MEASOBJECTEUTRA-START + +MeasObjectEUTRA::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + allowedMeasBandwidth EUTRA-AllowedMeasBandwidth, + cellsToRemoveListEUTRAN EUTRA-CellIndexList OPTIONAL, -- Need N + cellsToAddModListEUTRAN SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-Cell OPTIONAL, -- Need N + blackCellsToRemoveListEUTRAN EUTRA-CellIndexList OPTIONAL, -- Need N + blackCellsToAddModListEUTRAN SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-BlackCell OPTIONAL, -- Need N + eutra-PresenceAntennaPort1 EUTRA-PresenceAntennaPort1, + eutra-Q-OffsetRange EUTRA-Q-OffsetRange OPTIONAL, -- Need R + widebandRSRQ-Meas BOOLEAN, + ... +} + +EUTRA-CellIndexList ::= SEQUENCE (SIZE (1..maxCellMeasEUTRA)) OF EUTRA-CellIndex + +EUTRA-CellIndex ::= INTEGER (1..maxCellMeasEUTRA) + + +EUTRA-Cell ::= SEQUENCE { + cellIndexEUTRA EUTRA-CellIndex, + physCellId EUTRA-PhysCellId, + cellIndividualOffset EUTRA-Q-OffsetRange +} + + +EUTRA-BlackCell ::= SEQUENCE { + cellIndexEUTRA EUTRA-CellIndex, + physCellIdRange EUTRA-PhysCellIdRange +} + +-- TAG-MEASOBJECTEUTRA-STOP +-- TAG-MEASOBJECTID-START + +MeasObjectId ::= INTEGER (1..maxNrofObjectId) + +-- TAG-MEASOBJECTID-STOP +-- TAG-MEASOBJECTNR-START + +MeasObjectNR ::= SEQUENCE { + ssbFrequency ARFCN-ValueNR OPTIONAL, -- Cond SSBorAssociatedSSB + ssbSubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond SSBorAssociatedSSB + smtc1 SSB-MTC OPTIONAL, -- Cond SSBorAssociatedSSB + smtc2 SSB-MTC2 OPTIONAL, -- Cond IntraFreqConnected + refFreqCSI-RS ARFCN-ValueNR OPTIONAL, -- Cond CSI-RS + referenceSignalConfig ReferenceSignalConfig, + absThreshSS-BlocksConsolidation ThresholdNR OPTIONAL, -- Need R + absThreshCSI-RS-Consolidation ThresholdNR OPTIONAL, -- Need R + nrofSS-BlocksToAverage INTEGER (2..maxNrofSS-BlocksToAverage) OPTIONAL, -- Need R + nrofCSI-RS-ResourcesToAverage INTEGER (2..maxNrofCSI-RS-ResourcesToAverage) OPTIONAL, -- Need R + quantityConfigIndex INTEGER (1..maxNrofQuantityConfig), + offsetMO Q-OffsetRangeList, + cellsToRemoveList PCI-List OPTIONAL, -- Need N + cellsToAddModList CellsToAddModList OPTIONAL, -- Need N + blackCellsToRemoveList PCI-RangeIndexList OPTIONAL, -- Need N + blackCellsToAddModList SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeElement OPTIONAL, -- Need N + whiteCellsToRemoveList PCI-RangeIndexList OPTIONAL, -- Need N + whiteCellsToAddModList SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeElement OPTIONAL, -- Need N + ..., + [[ + freqBandIndicatorNR FreqBandIndicatorNR OPTIONAL, -- Need R + measCycleSCell ENUMERATED {sf160, sf256, sf320, sf512, sf640, sf1024, sf1280} OPTIONAL -- Need R + ]], + [[ + smtc3list-r16 SSB-MTC3List-r16 OPTIONAL, -- Need R + rmtc-Config-r16 SetupRelease {RMTC-Config-r16} OPTIONAL, -- Need M + t312-r16 SetupRelease { T312-r16 } OPTIONAL -- Need M + ]] +} + +SSB-MTC3List-r16::= SEQUENCE (SIZE(1..4)) OF SSB-MTC3-r16 + +T312-r16 ::= ENUMERATED { ms0, ms50, ms100, ms200, ms300, ms400, ms500, ms1000} + +ReferenceSignalConfig::= SEQUENCE { + ssb-ConfigMobility SSB-ConfigMobility OPTIONAL, -- Need M + csi-rs-ResourceConfigMobility SetupRelease { CSI-RS-ResourceConfigMobility } OPTIONAL -- Need M +} + +SSB-ConfigMobility::= SEQUENCE { + ssb-ToMeasure SetupRelease { SSB-ToMeasure } OPTIONAL, -- Need M + deriveSSB-IndexFromCell BOOLEAN, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL, -- Need M + ..., + [[ + ssb-PositionQCL-Common-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + ssb-PositionQCL-CellsToAddModList-r16 SSB-PositionQCL-CellsToAddModList-r16 OPTIONAL, -- Need N + ssb-PositionQCL-CellsToRemoveList-r16 PCI-List OPTIONAL -- Need N + ]] +} + +Q-OffsetRangeList ::= SEQUENCE { + rsrpOffsetSSB Q-OffsetRange DEFAULT dB0, + rsrqOffsetSSB Q-OffsetRange DEFAULT dB0, + sinrOffsetSSB Q-OffsetRange DEFAULT dB0, + rsrpOffsetCSI-RS Q-OffsetRange DEFAULT dB0, + rsrqOffsetCSI-RS Q-OffsetRange DEFAULT dB0, + sinrOffsetCSI-RS Q-OffsetRange DEFAULT dB0 +} + + +ThresholdNR ::= SEQUENCE{ + thresholdRSRP RSRP-Range OPTIONAL, -- Need R + thresholdRSRQ RSRQ-Range OPTIONAL, -- Need R + thresholdSINR SINR-Range OPTIONAL -- Need R +} + +CellsToAddModList ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF CellsToAddMod + +CellsToAddMod ::= SEQUENCE { + physCellId PhysCellId, + cellIndividualOffset Q-OffsetRangeList +} + +RMTC-Config-r16 ::= SEQUENCE { + rmtc-Periodicity-r16 ENUMERATED {ms40, ms80, ms160, ms320, ms640}, + rmtc-SubframeOffset-r16 INTEGER(0..639) OPTIONAL, -- Need M + measDurationSymbols-r16 ENUMERATED {sym1, sym14or12, sym28or24, sym42or36, sym70or60}, + rmtc-Frequency-r16 ARFCN-ValueNR, + ref-SCS-CP-r16 ENUMERATED {kHz15, kHz30, kHz60-NCP, kHz60-ECP}, + ... +} + +SSB-PositionQCL-CellsToAddModList-r16 ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF SSB-PositionQCL-CellsToAddMod-r16 + +SSB-PositionQCL-CellsToAddMod-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 +} + +-- TAG-MEASOBJECTNR-STOP +-- TAG-MEASOBJECTNR-SL-START + +MeasObjectNR-SL-r16 ::= SEQUENCE { + tx-PoolMeasToRemoveList-r16 Tx-PoolMeasList-r16 OPTIONAL, -- Need N + tx-PoolMeasToAddModList-r16 Tx-PoolMeasList-r16 OPTIONAL -- Need N +} + +Tx-PoolMeasList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-PoolToMeasureNR-r16)) OF SL-ResourcePoolID-r16 + +-- TAG-MEASOBJECTNR-SL-STOP +-- TAG-MEASOBJECTTOADDMODLIST-START + +MeasObjectToAddModList ::= SEQUENCE (SIZE (1..maxNrofObjectId)) OF MeasObjectToAddMod + +MeasObjectToAddMod ::= SEQUENCE { + measObjectId MeasObjectId, + measObject CHOICE { + measObjectNR MeasObjectNR, + ..., + measObjectEUTRA MeasObjectEUTRA, + measObjectUTRA-FDD-r16 MeasObjectUTRA-FDD-r16, + measObjectNR-SL-r16 MeasObjectNR-SL-r16, + measObjectCLI-r16 MeasObjectCLI-r16 + } +} + +-- TAG-MEASOBJECTTOADDMODLIST-STOP +-- TAG-MEASOBJECTUTRA-FDD-START + +MeasObjectUTRA-FDD-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueUTRA-FDD-r16, + utra-FDD-Q-OffsetRange-r16 UTRA-FDD-Q-OffsetRange-r16 OPTIONAL, -- Need R + cellsToRemoveList-r16 UTRA-FDD-CellIndexList-r16 OPTIONAL, -- Need N + cellsToAddModList-r16 CellsToAddModListUTRA-FDD-r16 OPTIONAL, -- Need N + ... +} + +CellsToAddModListUTRA-FDD-r16 ::= SEQUENCE (SIZE (1..maxCellMeasUTRA-FDD-r16)) OF CellsToAddModUTRA-FDD-r16 + +CellsToAddModUTRA-FDD-r16 ::= SEQUENCE { + cellIndexUTRA-FDD-r16 UTRA-FDD-CellIndex-r16, + physCellId-r16 PhysCellIdUTRA-FDD-r16 +} + +UTRA-FDD-CellIndexList-r16 ::= SEQUENCE (SIZE (1..maxCellMeasUTRA-FDD-r16)) OF UTRA-FDD-CellIndex-r16 + +UTRA-FDD-CellIndex-r16 ::= INTEGER (1..maxCellMeasUTRA-FDD-r16) + +-- TAG-MEASOBJECTUTRA-FDD-STOP +-- TAG-MEASRESULTCELLLISTSFTD-NR-START + +MeasResultCellListSFTD-NR ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF MeasResultCellSFTD-NR + +MeasResultCellSFTD-NR ::= SEQUENCE { + physCellId PhysCellId, + sfn-OffsetResult INTEGER (0..1023), + frameBoundaryOffsetResult INTEGER (-30720..30719), + rsrp-Result RSRP-Range OPTIONAL +} + +-- TAG-MEASRESULTCELLLISTSFTD-NR-STOP +-- TAG-MEASRESULTCELLLISTSFTD-EUTRA-START + +MeasResultCellListSFTD-EUTRA ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF MeasResultSFTD-EUTRA + +MeasResultSFTD-EUTRA ::= SEQUENCE { + eutra-PhysCellId EUTRA-PhysCellId, + sfn-OffsetResult INTEGER (0..1023), + frameBoundaryOffsetResult INTEGER (-30720..30719), + rsrp-Result RSRP-Range OPTIONAL +} + +-- TAG-MEASRESULTCELLLISTSFTD-EUTRA-STOP +-- TAG-MEASRESULTS-START + +MeasResults ::= SEQUENCE { + measId MeasId, + measResultServingMOList MeasResultServMOList, + measResultNeighCells CHOICE { + measResultListNR MeasResultListNR, + ..., + measResultListEUTRA MeasResultListEUTRA, + measResultListUTRA-FDD-r16 MeasResultListUTRA-FDD-r16 + } OPTIONAL, + ..., + [[ + measResultServFreqListEUTRA-SCG MeasResultServFreqListEUTRA-SCG OPTIONAL, + measResultServFreqListNR-SCG MeasResultServFreqListNR-SCG OPTIONAL, + measResultSFTD-EUTRA MeasResultSFTD-EUTRA OPTIONAL, + measResultSFTD-NR MeasResultCellSFTD-NR OPTIONAL + ]], + [[ + measResultCellListSFTD-NR MeasResultCellListSFTD-NR OPTIONAL + ]], + [[ + measResultForRSSI-r16 MeasResultForRSSI-r16 OPTIONAL, + locationInfo-r16 LocationInfo-r16 OPTIONAL, + ul-PDCP-DelayValueResultList-r16 UL-PDCP-DelayValueResultList-r16 OPTIONAL, + measResultsSL-r16 MeasResultsSL-r16 OPTIONAL, + measResultCLI-r16 MeasResultCLI-r16 OPTIONAL + ]] + + +} + +MeasResultServMOList ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF MeasResultServMO + +MeasResultServMO ::= SEQUENCE { + servCellId ServCellIndex, + measResultServingCell MeasResultNR, + measResultBestNeighCell MeasResultNR OPTIONAL, + ... +} + +MeasResultListNR ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultNR + +MeasResultNR ::= SEQUENCE { + physCellId PhysCellId OPTIONAL, + measResult SEQUENCE { + cellResults SEQUENCE{ + resultsSSB-Cell MeasQuantityResults OPTIONAL, + resultsCSI-RS-Cell MeasQuantityResults OPTIONAL + }, + rsIndexResults SEQUENCE{ + resultsSSB-Indexes ResultsPerSSB-IndexList OPTIONAL, + resultsCSI-RS-Indexes ResultsPerCSI-RS-IndexList OPTIONAL + } OPTIONAL + }, + ..., + [[ + cgi-Info CGI-InfoNR OPTIONAL + ]] +} + +MeasResultListEUTRA ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultEUTRA + +MeasResultEUTRA ::= SEQUENCE { + eutra-PhysCellId PhysCellId, + measResult MeasQuantityResultsEUTRA, + + cgi-Info CGI-InfoEUTRA OPTIONAL, + ... +} + +MultiBandInfoListEUTRA ::= SEQUENCE (SIZE (1..maxMultiBands)) OF FreqBandIndicatorEUTRA + +MeasQuantityResults ::= SEQUENCE { + rsrp RSRP-Range OPTIONAL, + rsrq RSRQ-Range OPTIONAL, + sinr SINR-Range OPTIONAL +} + +MeasQuantityResultsEUTRA ::= SEQUENCE { + rsrp RSRP-RangeEUTRA OPTIONAL, + rsrq RSRQ-RangeEUTRA OPTIONAL, + sinr SINR-RangeEUTRA OPTIONAL +} + +ResultsPerSSB-IndexList::= SEQUENCE (SIZE (1..maxNrofIndexesToReport2)) OF ResultsPerSSB-Index + +ResultsPerSSB-Index ::= SEQUENCE { + ssb-Index SSB-Index, + ssb-Results MeasQuantityResults OPTIONAL +} + +ResultsPerCSI-RS-IndexList::= SEQUENCE (SIZE (1..maxNrofIndexesToReport2)) OF ResultsPerCSI-RS-Index + +ResultsPerCSI-RS-Index ::= SEQUENCE { + csi-RS-Index CSI-RS-Index, + csi-RS-Results MeasQuantityResults OPTIONAL +} +MeasResultServFreqListEUTRA-SCG ::= SEQUENCE (SIZE (1..maxNrofServingCellsEUTRA)) OF MeasResult2EUTRA + +MeasResultServFreqListNR-SCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF MeasResult2NR + +MeasResultListUTRA-FDD-r16 ::= SEQUENCE (SIZE (1..maxCellReport)) OF MeasResultUTRA-FDD-r16 + +MeasResultUTRA-FDD-r16 ::= SEQUENCE { + physCellId-r16 PhysCellIdUTRA-FDD-r16, + measResult-r16 SEQUENCE { + utra-FDD-RSCP-r16 INTEGER (-5..91) OPTIONAL, + utra-FDD-EcN0-r16 INTEGER (0..49) OPTIONAL + } +} + +MeasResultForRSSI-r16 ::= SEQUENCE { + rssi-Result-r16 RSSI-Range-r16, + channelOccupancy-r16 INTEGER (0..100) +} + +MeasResultCLI-r16 ::= SEQUENCE { + measResultListSRS-RSRP-r16 MeasResultListSRS-RSRP-r16 OPTIONAL, + measResultListCLI-RSSI-r16 MeasResultListCLI-RSSI-r16 OPTIONAL +} + +MeasResultListSRS-RSRP-r16 ::= SEQUENCE (SIZE (1.. maxCLI-Report-r16)) OF MeasResultSRS-RSRP-r16 + +MeasResultSRS-RSRP-r16 ::= SEQUENCE { + srs-ResourceId-r16 SRS-ResourceId, + srs-RSRP-Result-r16 SRS-RSRP-Range-r16 +} + +MeasResultListCLI-RSSI-r16 ::= SEQUENCE (SIZE (1.. maxCLI-Report-r16)) OF MeasResultCLI-RSSI-r16 + +MeasResultCLI-RSSI-r16 ::= SEQUENCE { + rssi-ResourceId-r16 RSSI-ResourceId-r16, + cli-RSSI-Result-r16 CLI-RSSI-Range-r16 +} + +UL-PDCP-DelayValueResultList-r16 ::= SEQUENCE (SIZE (1..maxDRB)) OF UL-PDCP-DelayValueResult-r16 + +UL-PDCP-DelayValueResult-r16 ::= SEQUENCE { + drb-Id-r16 DRB-Identity, + averageDelay-r16 INTEGER (0..10000), + ... +} + +-- TAG-MEASRESULTS-STOP +-- TAG-MEASRESULT2EUTRA-START + +MeasResult2EUTRA ::= SEQUENCE { + carrierFreq ARFCN-ValueEUTRA, + measResultServingCell MeasResultEUTRA OPTIONAL, + measResultBestNeighCell MeasResultEUTRA OPTIONAL, + ... +} + +-- TAG-MEASRESULT2EUTRA-STOP +-- TAG-MEASRESULT2NR-START + +MeasResult2NR ::= SEQUENCE { + ssbFrequency ARFCN-ValueNR OPTIONAL, + refFreqCSI-RS ARFCN-ValueNR OPTIONAL, + measResultServingCell MeasResultNR OPTIONAL, + measResultNeighCellListNR MeasResultListNR OPTIONAL, + ... +} + +-- TAG-MEASRESULT2NR-STOP +-- TAG-MEASRESULTIDLEEUTRA-START + +MeasResultIdleEUTRA-r16 ::= SEQUENCE { + measResultsPerCarrierListIdleEUTRA-r16 SEQUENCE (SIZE (1.. maxFreqIdle-r16)) OF MeasResultsPerCarrierIdleEUTRA-r16, + ... +} + +MeasResultsPerCarrierIdleEUTRA-r16 ::= SEQUENCE { + carrierFreqEUTRA-r16 ARFCN-ValueEUTRA, + measResultsPerCellListIdleEUTRA-r16 SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF MeasResultsPerCellIdleEUTRA-r16, + ... +} + +MeasResultsPerCellIdleEUTRA-r16 ::= SEQUENCE { + eutra-PhysCellId-r16 EUTRA-PhysCellId, + measIdleResultEUTRA-r16 SEQUENCE { + rsrp-ResultEUTRA-r16 RSRP-RangeEUTRA OPTIONAL, + rsrq-ResultEUTRA-r16 RSRQ-RangeEUTRA-r16 OPTIONAL + }, + ... +} + +-- TAG-MEASRESULTIDLEEUTRA-STOP +-- TAG-MEASRESULTIDLENR-START + +MeasResultIdleNR-r16 ::= SEQUENCE { + measResultServingCell-r16 SEQUENCE { + rsrp-Result-r16 RSRP-Range OPTIONAL, + rsrq-Result-r16 RSRQ-Range OPTIONAL, + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList-r16 OPTIONAL + }, + measResultsPerCarrierListIdleNR-r16 SEQUENCE (SIZE (1.. maxFreqIdle-r16)) OF MeasResultsPerCarrierIdleNR-r16 OPTIONAL, + ... +} + +MeasResultsPerCarrierIdleNR-r16 ::= SEQUENCE { + carrierFreq-r16 ARFCN-ValueNR, + measResultsPerCellListIdleNR-r16 SEQUENCE (SIZE (1..maxCellMeasIdle-r16)) OF MeasResultsPerCellIdleNR-r16, + ... +} + +MeasResultsPerCellIdleNR-r16 ::= SEQUENCE { + physCellId-r16 PhysCellId, + measIdleResultNR-r16 SEQUENCE { + rsrp-Result-r16 RSRP-Range OPTIONAL, + rsrq-Result-r16 RSRQ-Range OPTIONAL, + resultsSSB-Indexes-r16 ResultsPerSSB-IndexList-r16 OPTIONAL + }, + ... +} + +ResultsPerSSB-IndexList-r16 ::= SEQUENCE (SIZE (1.. maxNrofIndexesToReport)) OF ResultsPerSSB-IndexIdle-r16 + +ResultsPerSSB-IndexIdle-r16 ::= SEQUENCE { + ssb-Index-r16 SSB-Index, + ssb-Results-r16 SEQUENCE { + ssb-RSRP-Result-r16 RSRP-Range OPTIONAL, + ssb-RSRQ-Result-r16 RSRQ-Range OPTIONAL + } OPTIONAL +} + +-- TAG-MEASRESULTIDLENR-STOP +-- TAG-MEASRESULTSCG-FAILURE-START + +MeasResultSCG-Failure ::= SEQUENCE { + measResultPerMOList MeasResultList2NR, + ..., + [[ + locationInfo-r16 LocationInfo-r16 OPTIONAL + ]] +} + +MeasResultList2NR ::= SEQUENCE (SIZE (1..maxFreq)) OF MeasResult2NR + +-- TAG-MEASRESULTSCG-FAILURE-STOP +-- TAG-MEASRESULTSSL-START + +MeasResultsSL-r16 ::= SEQUENCE { + measResultsListSL-r16 CHOICE { + measResultNR-SL-r16 MeasResultNR-SL-r16, + ... + }, + ... +} + +MeasResultNR-SL-r16 ::= SEQUENCE { + measResultListCBR-NR-r16 SEQUENCE (SIZE (1.. maxNrofSL-PoolToMeasureNR-r16)) OF MeasResultCBR-NR-r16, + ... +} + +MeasResultCBR-NR-r16 ::= SEQUENCE { + sl-poolReportIdentity-r16 SL-ResourcePoolID-r16, + sl-CBR-ResultsNR-r16 SL-CBR-r16, + ... +} + +-- TAG-MEASRESULTSSL-STOP +-- TAG-MEASTRIGGERQUANTITYEUTRA-START + +MeasTriggerQuantityEUTRA::= CHOICE { + rsrp RSRP-RangeEUTRA, + rsrq RSRQ-RangeEUTRA, + sinr SINR-RangeEUTRA +} + +RSRP-RangeEUTRA ::= INTEGER (0..97) + +RSRQ-RangeEUTRA ::= INTEGER (0..34) + +SINR-RangeEUTRA ::= INTEGER (0..127) + +-- TAG-MEASTRIGGERQUANTITYEUTRA-STOP +-- TAG-MOBILITYSTATEPARAMETERS-START + +MobilityStateParameters ::= SEQUENCE{ + t-Evaluation ENUMERATED { + s30, s60, s120, s180, s240, spare3, spare2, spare1}, + t-HystNormal ENUMERATED { + s30, s60, s120, s180, s240, spare3, spare2, spare1}, + n-CellChangeMedium INTEGER (1..16), + n-CellChangeHigh INTEGER (1..16) +} + +-- TAG-MOBILITYSTATEPARAMETERS-STOP +-- TAG-MSGACONFIGCOMMON-START + +MsgA-ConfigCommon-r16 ::= SEQUENCE { + rach-ConfigCommonTwoStepRA-r16 RACH-ConfigCommonTwoStepRA-r16, + msgA-PUSCH-Config-r16 MsgA-PUSCH-Config-r16 OPTIONAL --Cond InitialBWPConfig +} +-- TAG-MSGACONFIGCOMMON-STOP +-- TAG-MSGA-PUSCH-CONFIG-START + +MsgA-PUSCH-Config-r16 ::= SEQUENCE { + msgA-PUSCH-ResourceGroupA-r16 MsgA-PUSCH-Resource-r16 OPTIONAL, -- Cond InitialBWPConfig + msgA-PUSCH-ResourceGroupB-r16 MsgA-PUSCH-Resource-r16 OPTIONAL, -- Cond GroupBConfigured + msgA-TransformPrecoder-r16 ENUMERATED {enabled, disabled} OPTIONAL, -- Need R + msgA-DataScramblingIndex-r16 INTEGER (0..1023) OPTIONAL, -- Need S + msgA-DeltaPreamble-r16 INTEGER (-1..6) OPTIONAL -- Need R +} + +MsgA-PUSCH-Resource-r16 ::= SEQUENCE { + msgA-MCS-r16 INTEGER (0..15), + nrofSlotsMsgA-PUSCH-r16 INTEGER (1..4), + nrofMsgA-PO-PerSlot-r16 ENUMERATED {one, two, three, six}, + msgA-PUSCH-TimeDomainOffset-r16 INTEGER (1..32), + msgA-PUSCH-TimeDomainAllocation-r16 INTEGER (1..maxNrofUL-Allocations) OPTIONAL, -- Need S + startSymbolAndLengthMsgA-PO-r16 INTEGER (0..127) OPTIONAL, -- Need S + mappingTypeMsgA-PUSCH-r16 ENUMERATED {typeA, typeB} OPTIONAL, -- Need S + guardPeriodMsgA-PUSCH-r16 INTEGER (0..3) OPTIONAL, -- Need R + guardBandMsgA-PUSCH-r16 INTEGER (0..1), + frequencyStartMsgA-PUSCH-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1), + nrofPRBs-PerMsgA-PO-r16 INTEGER (1..32), + nrofMsgA-PO-FDM-r16 ENUMERATED {one, two, four, eight}, + msgA-IntraSlotFrequencyHopping-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + msgA-HoppingBits-r16 BIT STRING (SIZE(2)) OPTIONAL, -- Cond FreqHopConfigured + msgA-DMRS-Config-r16 MsgA-DMRS-Config-r16, + nrofDMRS-Sequences-r16 INTEGER (1..2), + msgA-Alpha-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, + alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need S + interlaceIndexFirstPO-MsgA-PUSCH-r16 INTEGER (1..10) OPTIONAL, -- Need R + nrofInterlacesPerMsgA-PO-r16 INTEGER (1..10) OPTIONAL, -- Need R + ... +} + +MsgA-DMRS-Config-r16 ::= SEQUENCE { + msgA-DMRS-AdditionalPosition-r16 ENUMERATED {pos0, pos1, pos3} OPTIONAL, -- Need S + msgA-MaxLength-r16 ENUMERATED {len2} OPTIONAL, -- Need S + msgA-PUSCH-DMRS-CDM-Group-r16 INTEGER (0..1) OPTIONAL, -- Need S + msgA-PUSCH-NrofPorts-r16 INTEGER (0..1) OPTIONAL, -- Need S + msgA-ScramblingID0-r16 INTEGER (0..65535) OPTIONAL, -- Need S + msgA-ScramblingID1-r16 INTEGER (0..65535) OPTIONAL -- Need S +} + +-- TAG-MSGA-PUSCH-CONFIG-STOP +-- TAG-MULTIFREQUENCYBANDLISTNR-START + +MultiFrequencyBandListNR ::= SEQUENCE (SIZE (1..maxNrofMultiBands)) OF FreqBandIndicatorNR + +-- TAG-MULTIFREQUENCYBANDLISTNR-STOP +-- TAG-MULTIFREQUENCYBANDLISTNR-SIB-START + +MultiFrequencyBandListNR-SIB ::= SEQUENCE (SIZE (1.. maxNrofMultiBands)) OF NR-MultiBandInfo + +NR-MultiBandInfo ::= SEQUENCE { + freqBandIndicatorNR FreqBandIndicatorNR OPTIONAL, -- Cond OptULNotSIB2 + nr-NS-PmaxList NR-NS-PmaxList OPTIONAL -- Need S +} + +-- TAG-MULTIFREQUENCYBANDLISTNR-SIB-STOP +-- TAG-NeedForGapsConfigNR-START + +NeedForGapsConfigNR-r16 ::= SEQUENCE { + requestedTargetBandFilterNR-r16 SEQUENCE (SIZE (1..maxBands)) OF FreqBandIndicatorNR OPTIONAL -- Need R +} + +-- TAG-NeedForGapsConfigNR-STOP +-- TAG-NeedForGapsInfoNR-START + +NeedForGapsInfoNR-r16 ::= SEQUENCE { + intraFreq-needForGap-r16 NeedForGapsIntraFreqlist-r16, + interFreq-needForGap-r16 NeedForGapsBandlistNR-r16 +} + +NeedForGapsIntraFreqlist-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCells)) OF NeedForGapsIntraFreq-r16 + +NeedForGapsBandlistNR-r16 ::= SEQUENCE (SIZE (1..maxBands)) OF NeedForGapsNR-r16 + +NeedForGapsIntraFreq-r16 ::= SEQUENCE { + servCellId-r16 ServCellIndex, + gapIndicationIntra-r16 ENUMERATED {gap, no-gap} +} + +NeedForGapsNR-r16 ::= SEQUENCE { + bandNR-r16 FreqBandIndicatorNR, + gapIndication-r16 ENUMERATED {gap, no-gap} +} + +-- TAG-NeedForGapsInfoNR-STOP +-- TAG-NEXTHOPCHAININGCOUNT-START + +NextHopChainingCount ::= INTEGER (0..7) + +-- TAG-NEXTHOPCHAININGCOUNT-STOP +-- TAG-NG-5G-S-TMSI-START + +NG-5G-S-TMSI ::= BIT STRING (SIZE (48)) + +-- TAG-NG-5G-S-TMSI-STOP +-- TAG-NPN-IDENTITY-START + +NPN-Identity-r16 ::= CHOICE { + pni-npn-r16 SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + cag-IdentityList-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF CAG-IdentityInfo-r16 + }, + snpn-r16 SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + nid-List-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF NID-r16 + } +} + +CAG-IdentityInfo-r16 ::= SEQUENCE { + cag-Identity-r16 BIT STRING (SIZE (32)), + manualCAGselectionAllowed-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +NID-r16 ::= BIT STRING (SIZE (44)) + +-- TAG-NPN-IDENTITY-STOP +-- TAG-NPN-IDENTITYINFOLIST-START + +NPN-IdentityInfoList-r16 ::= SEQUENCE (SIZE (1..maxNPN-r16)) OF NPN-IdentityInfo-r16 + + +NPN-IdentityInfo-r16 ::= SEQUENCE { + npn-IdentityList-r16 SEQUENCE (SIZE (1..maxNPN-r16)) OF NPN-Identity-r16, + trackingAreaCode-r16 TrackingAreaCode, + ranac-r16 RAN-AreaCode OPTIONAL, -- Need R + cellIdentity-r16 CellIdentity, + cellReservedForOperatorUse-r16 ENUMERATED {reserved, notReserved}, + iab-Support-r16 ENUMERATED {true} OPTIONAL, -- Need S + ... +} + +-- TAG-NPN-IDENTITYINFOLIST-STOP +-- TAG-NR-NS-PMAXLIST-START + +NR-NS-PmaxList ::= SEQUENCE (SIZE (1..maxNR-NS-Pmax)) OF NR-NS-PmaxValue + +NR-NS-PmaxValue ::= SEQUENCE { + additionalPmax P-Max OPTIONAL, -- Need N + additionalSpectrumEmission AdditionalSpectrumEmission +} + +-- TAG-NR-NS-PMAXLIST-STOP +-- TAG-NZP-CSI-RS-RESOURCE-START + +NZP-CSI-RS-Resource ::= SEQUENCE { + nzp-CSI-RS-ResourceId NZP-CSI-RS-ResourceId, + resourceMapping CSI-RS-ResourceMapping, + powerControlOffset INTEGER (-8..15), + powerControlOffsetSS ENUMERATED{db-3, db0, db3, db6} OPTIONAL, -- Need R + scramblingID ScramblingId, + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, -- Cond PeriodicOrSemiPersistent + qcl-InfoPeriodicCSI-RS TCI-StateId OPTIONAL, -- Cond Periodic + ... +} + +-- TAG-NZP-CSI-RS-RESOURCE-STOP +-- TAG-NZP-CSI-RS-RESOURCEID-START + +NZP-CSI-RS-ResourceId ::= INTEGER (0..maxNrofNZP-CSI-RS-Resources-1) + +-- TAG-NZP-CSI-RS-RESOURCEID-STOP +-- TAG-NZP-CSI-RS-RESOURCESET-START +NZP-CSI-RS-ResourceSet ::= SEQUENCE { + nzp-CSI-ResourceSetId NZP-CSI-RS-ResourceSetId, + nzp-CSI-RS-Resources SEQUENCE (SIZE (1..maxNrofNZP-CSI-RS-ResourcesPerSet)) OF NZP-CSI-RS-ResourceId, + repetition ENUMERATED { on, off } OPTIONAL, -- Need S + aperiodicTriggeringOffset INTEGER(0..6) OPTIONAL, -- Need S + trs-Info ENUMERATED {true} OPTIONAL, -- Need R + ..., + [[ + aperiodicTriggeringOffset-r16 INTEGER(0..31) OPTIONAL -- Need S + ]] +} + +-- TAG-NZP-CSI-RS-RESOURCESET-STOP +-- TAG-NZP-CSI-RS-RESOURCESETID-START + +NZP-CSI-RS-ResourceSetId ::= INTEGER (0..maxNrofNZP-CSI-RS-ResourceSets-1) + +-- TAG-NZP-CSI-RS-RESOURCESETID-STOP +-- TAG-P-MAX-START + +P-Max ::= INTEGER (-30..33) + +-- TAG-P-MAX-STOP +-- TAG-PCI-LIST-START + +PCI-List ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF PhysCellId + +-- TAG-PCI-LIST-STOP +-- TAG-PCI-RANGE-START + +PCI-Range ::= SEQUENCE { + start PhysCellId, + range ENUMERATED {n4, n8, n12, n16, n24, n32, n48, n64, n84, + n96, n128, n168, n252, n504, n1008,spare1} OPTIONAL -- Need S +} + +-- TAG-PCI-RANGE-STOP +-- TAG-PCI-RANGEELEMENT-START + +PCI-RangeElement ::= SEQUENCE { + pci-RangeIndex PCI-RangeIndex, + pci-Range PCI-Range +} + +-- TAG-PCI-RANGEELEMENT-STOP +-- TAG-PCI-RANGEINDEX-START + +PCI-RangeIndex ::= INTEGER (1..maxNrofPCI-Ranges) + +-- TAG-PCI-RANGEINDEX-STOP +-- TAG-PCI-RANGEINDEXLIST-START + +PCI-RangeIndexList ::= SEQUENCE (SIZE (1..maxNrofPCI-Ranges)) OF PCI-RangeIndex + +-- TAG-PCI-RANGEINDEXLIST-STOP +-- TAG-PDCCH-CONFIG-START + +PDCCH-Config ::= SEQUENCE { + controlResourceSetToAddModList SEQUENCE(SIZE (1..3)) OF ControlResourceSet OPTIONAL, -- Need N + controlResourceSetToReleaseList SEQUENCE(SIZE (1..3)) OF ControlResourceSetId OPTIONAL, -- Need N + searchSpacesToAddModList SEQUENCE(SIZE (1..10)) OF SearchSpace OPTIONAL, -- Need N + searchSpacesToReleaseList SEQUENCE(SIZE (1..10)) OF SearchSpaceId OPTIONAL, -- Need N + downlinkPreemption SetupRelease { DownlinkPreemption } OPTIONAL, -- Need M + tpc-PUSCH SetupRelease { PUSCH-TPC-CommandConfig } OPTIONAL, -- Need M + tpc-PUCCH SetupRelease { PUCCH-TPC-CommandConfig } OPTIONAL, -- Need M + tpc-SRS SetupRelease { SRS-TPC-CommandConfig} OPTIONAL, -- Need M + ..., + [[ + controlResourceSetToAddModListSizeExt-v1610 SEQUENCE (SIZE (1..2)) OF ControlResourceSet OPTIONAL, -- Need N + controlResourceSetToReleaseListSizeExt-r16 SEQUENCE (SIZE (1..5)) OF ControlResourceSetId-r16 OPTIONAL, -- Need N + searchSpacesToAddModListExt-r16 SEQUENCE(SIZE (1..10)) OF SearchSpaceExt-r16 OPTIONAL, -- Need N + uplinkCancellation-r16 SetupRelease { UplinkCancellation-r16 } OPTIONAL, -- Need M + monitoringCapabilityConfig-r16 ENUMERATED { r15monitoringcapability,r16monitoringcapability } OPTIONAL, -- Need M + searchSpaceSwitchConfig-r16 SearchSpaceSwitchConfig-r16 OPTIONAL -- Need R + ]] +} + +SearchSpaceSwitchConfig-r16 ::= SEQUENCE { + cellGroupsForSwitchList-r16 SEQUENCE(SIZE (1..4)) OF CellGroupForSwitch-r16 OPTIONAL, -- Need R + searchSpaceSwitchDelay-r16 INTEGER (10..52) OPTIONAL -- Need R +} + +CellGroupForSwitch-r16 ::= SEQUENCE(SIZE (1..16)) OF ServCellIndex + +-- TAG-PDCCH-CONFIG-STOP +-- TAG-PDCCH-CONFIGCOMMON-START + +PDCCH-ConfigCommon ::= SEQUENCE { + controlResourceSetZero ControlResourceSetZero OPTIONAL, -- Cond InitialBWP-Only + commonControlResourceSet ControlResourceSet OPTIONAL, -- Need R + searchSpaceZero SearchSpaceZero OPTIONAL, -- Cond InitialBWP-Only + commonSearchSpaceList SEQUENCE (SIZE(1..4)) OF SearchSpace OPTIONAL, -- Need R + searchSpaceSIB1 SearchSpaceId OPTIONAL, -- Need S + searchSpaceOtherSystemInformation SearchSpaceId OPTIONAL, -- Need S + pagingSearchSpace SearchSpaceId OPTIONAL, -- Need S + ra-SearchSpace SearchSpaceId OPTIONAL, -- Need S + ..., + [[ + firstPDCCH-MonitoringOccasionOfPO CHOICE { + sCS15KHZoneT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..139), + sCS30KHZoneT-SCS15KHZhalfT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..279), + sCS60KHZoneT-SCS30KHZhalfT-SCS15KHZquarterT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..559), + sCS120KHZoneT-SCS60KHZhalfT-SCS30KHZquarterT-SCS15KHZoneEighthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..1119), + sCS120KHZhalfT-SCS60KHZquarterT-SCS30KHZoneEighthT-SCS15KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..2239), + sCS120KHZquarterT-SCS60KHZoneEighthT-SCS30KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..4479), + sCS120KHZoneEighthT-SCS60KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..8959), + sCS120KHZoneSixteenthT SEQUENCE (SIZE (1..maxPO-perPF)) OF INTEGER (0..17919) + } OPTIONAL -- Cond OtherBWP + ]], + [[ + commonSearchSpaceListExt-r16 SEQUENCE (SIZE(1..4)) OF SearchSpaceExt-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-PDCCH-CONFIGCOMMON-STOP +-- TAG-PDCCH-CONFIGSIB1-START + +PDCCH-ConfigSIB1 ::= SEQUENCE { + controlResourceSetZero ControlResourceSetZero, + searchSpaceZero SearchSpaceZero +} + +-- TAG-PDCCH-CONFIGSIB1-STOP +-- TAG-PDCCH-SERVINGCELLCONFIG-START + +PDCCH-ServingCellConfig ::= SEQUENCE { + slotFormatIndicator SetupRelease { SlotFormatIndicator } OPTIONAL, -- Need M + ..., + [[ + availabilityIndicator-r16 SetupRelease {AvailabilityIndicator-r16} OPTIONAL, -- Need M + searchSpaceSwitchTimer-r16 INTEGER (1..80) OPTIONAL -- Need R + ]] +} + +-- TAG-PDCCH-SERVINGCELLCONFIG-STOP +-- TAG-PDCP-CONFIG-START + +PDCP-Config ::= SEQUENCE { + drb SEQUENCE { + discardTimer ENUMERATED {ms10, ms20, ms30, ms40, ms50, ms60, ms75, ms100, ms150, ms200, + ms250, ms300, ms500, ms750, ms1500, infinity} OPTIONAL, -- Cond Setup + pdcp-SN-SizeUL ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + pdcp-SN-SizeDL ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + headerCompression CHOICE { + notUsed NULL, + rohc SEQUENCE { + maxCID INTEGER (1..16383) DEFAULT 15, + profiles SEQUENCE { + profile0x0001 BOOLEAN, + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0101 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + drb-ContinueROHC ENUMERATED { true } OPTIONAL -- Need N + }, + uplinkOnlyROHC SEQUENCE { + maxCID INTEGER (1..16383) DEFAULT 15, + profiles SEQUENCE { + profile0x0006 BOOLEAN + }, + drb-ContinueROHC ENUMERATED { true } OPTIONAL -- Need N + }, + ... + }, + integrityProtection ENUMERATED { enabled } OPTIONAL, -- Cond ConnectedTo5GC1 + statusReportRequired ENUMERATED { true } OPTIONAL, -- Cond Rlc-AM-UM + outOfOrderDelivery ENUMERATED { true } OPTIONAL -- Need R + } OPTIONAL, -- Cond DRB + moreThanOneRLC SEQUENCE { + primaryPath SEQUENCE { + cellGroup CellGroupId OPTIONAL, -- Need R + logicalChannel LogicalChannelIdentity OPTIONAL -- Need R + }, + ul-DataSplitThreshold UL-DataSplitThreshold OPTIONAL, -- Cond SplitBearer + pdcp-Duplication BOOLEAN OPTIONAL -- Need R + } OPTIONAL, -- Cond MoreThanOneRLC + + t-Reordering ENUMERATED { + ms0, ms1, ms2, ms4, ms5, ms8, ms10, ms15, ms20, ms30, ms40, + ms50, ms60, ms80, ms100, ms120, ms140, ms160, ms180, ms200, ms220, + ms240, ms260, ms280, ms300, ms500, ms750, ms1000, ms1250, + ms1500, ms1750, ms2000, ms2250, ms2500, ms2750, + ms3000, spare28, spare27, spare26, spare25, spare24, + spare23, spare22, spare21, spare20, + spare19, spare18, spare17, spare16, spare15, spare14, + spare13, spare12, spare11, spare10, spare09, + spare08, spare07, spare06, spare05, spare04, spare03, + spare02, spare01 } OPTIONAL, -- Need S + ..., + [[ + cipheringDisabled ENUMERATED {true} OPTIONAL -- Cond ConnectedTo5GC + ]], + [[ + discardTimerExt-r16 SetupRelease { DiscardTimerExt-r16 } OPTIONAL, -- Cond DRB2 + moreThanTwoRLC-DRB-r16 SEQUENCE { + splitSecondaryPath-r16 LogicalChannelIdentity OPTIONAL, -- Cond SplitBearer2 + duplicationState-r16 SEQUENCE (SIZE (3)) OF BOOLEAN OPTIONAL -- Need S + } OPTIONAL, -- Cond MoreThanTwoRLC-DRB + ethernetHeaderCompression-r16 SetupRelease { EthernetHeaderCompression-r16 } OPTIONAL -- Need M + ]] +} + +EthernetHeaderCompression-r16 ::= SEQUENCE { + ehc-Common-r16 SEQUENCE { + ehc-CID-Length-r16 ENUMERATED { bits7, bits15 }, + ... + }, + ehc-Downlink-r16 SEQUENCE { + drb-ContinueEHC-DL-r16 ENUMERATED { true } OPTIONAL, -- Need R + ... + } OPTIONAL, -- Need M + ehc-Uplink-r16 SEQUENCE { + maxCID-EHC-UL-r16 INTEGER (1..32767), + drb-ContinueEHC-UL-r16 ENUMERATED { true } OPTIONAL, -- Need R + ... + } OPTIONAL -- Need M +} + +UL-DataSplitThreshold ::= ENUMERATED { + b0, b100, b200, b400, b800, b1600, b3200, b6400, b12800, b25600, b51200, b102400, b204800, + b409600, b819200, b1228800, b1638400, b2457600, b3276800, b4096000, b4915200, b5734400, + b6553600, infinity, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1} + +DiscardTimerExt-r16 ::= ENUMERATED {ms0dot5, ms1, ms2, ms4, ms6, ms8, spare2, spare1} + +-- TAG-PDCP-CONFIG-STOP +-- TAG-PDSCH-CONFIG-START + +PDSCH-Config ::= SEQUENCE { + dataScramblingIdentityPDSCH INTEGER (0..1023) OPTIONAL, -- Need S + dmrs-DownlinkForPDSCH-MappingTypeA SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-DownlinkForPDSCH-MappingTypeB SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + + tci-StatesToAddModList SEQUENCE (SIZE(1..maxNrofTCI-States)) OF TCI-State OPTIONAL, -- Need N + tci-StatesToReleaseList SEQUENCE (SIZE(1..maxNrofTCI-States)) OF TCI-StateId OPTIONAL, -- Need N + vrb-ToPRB-Interleaver ENUMERATED {n2, n4} OPTIONAL, -- Need S + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch}, + pdsch-TimeDomainAllocationList SetupRelease { PDSCH-TimeDomainResourceAllocationList } OPTIONAL, -- Need M + pdsch-AggregationFactor ENUMERATED { n2, n4, n8 } OPTIONAL, -- Need S + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + rateMatchPatternGroup1 RateMatchPatternGroup OPTIONAL, -- Need R + rateMatchPatternGroup2 RateMatchPatternGroup OPTIONAL, -- Need R + + rbg-Size ENUMERATED {config1, config2}, + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + maxNrofCodeWordsScheduledByDCI ENUMERATED {n1, n2} OPTIONAL, -- Need R + + prb-BundlingType CHOICE { + staticBundling SEQUENCE { + bundleSize ENUMERATED { n4, wideband } OPTIONAL -- Need S + }, + dynamicBundling SEQUENCE { + bundleSizeSet1 ENUMERATED { n4, wideband, n2-wideband, n4-wideband } OPTIONAL, -- Need S + bundleSizeSet2 ENUMERATED { n4, wideband } OPTIONAL -- Need S + } + }, + zp-CSI-RS-ResourceToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-Resources)) OF ZP-CSI-RS-Resource + OPTIONAL, -- Need N + zp-CSI-RS-ResourceToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-Resources)) OF ZP-CSI-RS-ResourceId + OPTIONAL, -- Need N + aperiodic-ZP-CSI-RS-ResourceSetsToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + aperiodic-ZP-CSI-RS-ResourceSetsToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + sp-ZP-CSI-RS-ResourceSetsToAddModList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + sp-ZP-CSI-RS-ResourceSetsToReleaseList SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + p-ZP-CSI-RS-ResourceSet SetupRelease { ZP-CSI-RS-ResourceSet } + OPTIONAL, -- Need M + ..., + [[ + maxMIMO-Layers-r16 SetupRelease { MaxMIMO-LayersDL-r16 } OPTIONAL, -- Need M + minimumSchedulingOffsetK0-r16 SetupRelease { MinSchedulingOffsetK0-Values-r16 } OPTIONAL, -- Need M + + -- Start of the parameters for DCI format 1_2 introduced in V16.1.0 + antennaPortsFieldPresenceDCI-1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + aperiodicZP-CSI-RS-ResourceSetsToAddModListDCI-1-2-r16 SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSet + OPTIONAL, -- Need N + aperiodicZP-CSI-RS-ResourceSetsToReleaseListDCI-1-2-r16 SEQUENCE (SIZE (1..maxNrofZP-CSI-RS-ResourceSets)) OF ZP-CSI-RS-ResourceSetId + OPTIONAL, -- Need N + dmrs-DownlinkForPDSCH-MappingTypeA-DCI-1-2-r16 SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-DownlinkForPDSCH-MappingTypeB-DCI-1-2-r16 SetupRelease { DMRS-DownlinkConfig } OPTIONAL, -- Need M + dmrs-SequenceInitializationDCI-1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + harq-ProcessNumberSizeDCI-1-2-r16 INTEGER (0..4) OPTIONAL, -- Need R + mcs-TableDCI-1-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + numberOfBitsForRV-DCI-1-2-r16 INTEGER (0..2) OPTIONAL, -- Need R + pdsch-TimeDomainAllocationListDCI-1-2-r16 SetupRelease { PDSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + prb-BundlingTypeDCI-1-2-r16 CHOICE { + staticBundling-r16 SEQUENCE { + bundleSize-r16 ENUMERATED { n4, wideband } OPTIONAL -- Need S + }, + dynamicBundling-r16 SEQUENCE { + bundleSizeSet1-r16 ENUMERATED { n4, wideband, n2-wideband, n4-wideband } OPTIONAL, -- Need S + bundleSizeSet2-r16 ENUMERATED { n4, wideband } OPTIONAL -- Need S + } + } OPTIONAL, -- Need R + priorityIndicatorDCI-1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + rateMatchPatternGroup1DCI-1-2-r16 RateMatchPatternGroup OPTIONAL, -- Need R + rateMatchPatternGroup2DCI-1-2-r16 RateMatchPatternGroup OPTIONAL, -- Need R + resourceAllocationType1GranularityDCI-1-2-r16 ENUMERATED {n2,n4,n8,n16} OPTIONAL, -- Need S + vrb-ToPRB-InterleaverDCI-1-2-r16 ENUMERATED {n2, n4} OPTIONAL, -- Need S + referenceOfSLIVDCI-1-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + resourceAllocationDCI-1-2-r16 ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch} + OPTIONAL, -- Need M + -- End of the parameters for DCI format 1_2 introduced in V16.1.0 + + priorityIndicatorDCI-1-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + dataScramblingIdentityPDSCH2-r16 INTEGER (0..1023) OPTIONAL, -- Need R + pdsch-TimeDomainAllocationList-r16 SetupRelease { PDSCH-TimeDomainResourceAllocationList-r16 } OPTIONAL, -- Need M + repetitionSchemeConfig-r16 SetupRelease { RepetitionSchemeConfig-r16} OPTIONAL -- Need M + ]], + [[ + repetitionSchemeConfig-v1630 SetupRelease { RepetitionSchemeConfig-v1630} OPTIONAL -- Need M + ]] +} + +RateMatchPatternGroup ::= SEQUENCE (SIZE (1..maxNrofRateMatchPatternsPerGroup)) OF CHOICE { + cellLevel RateMatchPatternId, + bwpLevel RateMatchPatternId +} + +MinSchedulingOffsetK0-Values-r16 ::= SEQUENCE (SIZE (1..maxNrOfMinSchedulingOffsetValues-r16)) OF INTEGER (0..maxK0-SchedulingOffset-r16) + +MaxMIMO-LayersDL-r16 ::= INTEGER (1..8) + +-- TAG-PDSCH-CONFIG-STOP +-- TAG-PDSCH-CONFIGCOMMON-START + +PDSCH-ConfigCommon ::= SEQUENCE { + pdsch-TimeDomainAllocationList PDSCH-TimeDomainResourceAllocationList OPTIONAL, -- Need R + ... +} + +-- TAG-PDSCH-CONFIGCOMMON-STOP +-- TAG-PDSCH-SERVINGCELLCONFIG-START + +PDSCH-ServingCellConfig ::= SEQUENCE { + codeBlockGroupTransmission SetupRelease { PDSCH-CodeBlockGroupTransmission } OPTIONAL, -- Need M + xOverhead ENUMERATED { xOh6, xOh12, xOh18 } OPTIONAL, -- Need S + nrofHARQ-ProcessesForPDSCH ENUMERATED {n2, n4, n6, n10, n12, n16} OPTIONAL, -- Need S + pucch-Cell ServCellIndex OPTIONAL, -- Cond SCellAddOnly + ..., + [[ + maxMIMO-Layers INTEGER (1..8) OPTIONAL, -- Need M + processingType2Enabled BOOLEAN OPTIONAL -- Need M + ]], + [[ + pdsch-CodeBlockGroupTransmissionList-r16 SetupRelease { PDSCH-CodeBlockGroupTransmissionList-r16 } OPTIONAL -- Need M + ]] +} + +PDSCH-CodeBlockGroupTransmission ::= SEQUENCE { + maxCodeBlockGroupsPerTransportBlock ENUMERATED {n2, n4, n6, n8}, + codeBlockGroupFlushIndicator BOOLEAN, + ... +} + +PDSCH-CodeBlockGroupTransmissionList-r16 ::= SEQUENCE (SIZE (1..2)) OF PDSCH-CodeBlockGroupTransmission + +-- TAG-PDSCH-SERVINGCELLCONFIG-STOP +-- TAG-PDSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-START + + +PDSCH-TimeDomainResourceAllocationList ::= SEQUENCE (SIZE(1..maxNrofDL-Allocations)) OF PDSCH-TimeDomainResourceAllocation + +PDSCH-TimeDomainResourceAllocation ::= SEQUENCE { + k0 INTEGER(0..32) OPTIONAL, -- Need S + mappingType ENUMERATED {typeA, typeB}, + startSymbolAndLength INTEGER (0..127) +} + +PDSCH-TimeDomainResourceAllocationList-r16 ::= SEQUENCE (SIZE(1..maxNrofDL-Allocations)) OF PDSCH-TimeDomainResourceAllocation-r16 + +PDSCH-TimeDomainResourceAllocation-r16 ::= SEQUENCE { + k0-r16 INTEGER(0..32) OPTIONAL, -- Need S + mappingType-r16 ENUMERATED {typeA, typeB}, + startSymbolAndLength-r16 INTEGER (0..127), + repetitionNumber-r16 ENUMERATED {n2, n3, n4, n5, n6, n7, n8, n16} OPTIONAL, -- Cond Formats1-0and1-1 + ... +} + +-- TAG-PDSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-STOP +-- TAG-PHR-CONFIG-START + +PHR-Config ::= SEQUENCE { + phr-PeriodicTimer ENUMERATED {sf10, sf20, sf50, sf100, sf200,sf500, sf1000, infinity}, + phr-ProhibitTimer ENUMERATED {sf0, sf10, sf20, sf50, sf100,sf200, sf500, sf1000}, + phr-Tx-PowerFactorChange ENUMERATED {dB1, dB3, dB6, infinity}, + multiplePHR BOOLEAN, + dummy BOOLEAN, + phr-Type2OtherCell BOOLEAN, + phr-ModeOtherCG ENUMERATED {real, virtual}, + ..., + [[ + mpe-Reporting-FR2-r16 SetupRelease { MPE-Config-FR2-r16 } OPTIONAL -- Need M + ]] +} + +MPE-Config-FR2-r16 ::= SEQUENCE { + mpe-ProhibitTimer-r16 ENUMERATED {sf0, sf10, sf20, sf50, sf100, sf200, sf500, sf1000}, + mpe-Threshold-r16 ENUMERATED {dB3, dB6, dB9, dB12} +} + +-- TAG-PHR-CONFIG-STOP +-- TAG-PHYSCELLID-START + +PhysCellId ::= INTEGER (0..1007) + +-- TAG-PHYSCELLID-STOP +-- TAG-PHYSICALCELLGROUPCONFIG-START + +PhysicalCellGroupConfig ::= SEQUENCE { + harq-ACK-SpatialBundlingPUCCH ENUMERATED {true} OPTIONAL, -- Need S + harq-ACK-SpatialBundlingPUSCH ENUMERATED {true} OPTIONAL, -- Need S + p-NR-FR1 P-Max OPTIONAL, -- Need R + pdsch-HARQ-ACK-Codebook ENUMERATED {semiStatic, dynamic}, + tpc-SRS-RNTI RNTI-Value OPTIONAL, -- Need R + tpc-PUCCH-RNTI RNTI-Value OPTIONAL, -- Need R + tpc-PUSCH-RNTI RNTI-Value OPTIONAL, -- Need R + sp-CSI-RNTI RNTI-Value OPTIONAL, -- Need R + cs-RNTI SetupRelease { RNTI-Value } OPTIONAL, -- Need M + ..., + [[ + mcs-C-RNTI RNTI-Value OPTIONAL, -- Need R + p-UE-FR1 P-Max OPTIONAL -- Cond MCG-Only + ]], + [[ + xScale ENUMERATED {dB0, dB6, spare2, spare1} OPTIONAL -- Cond SCG-Only + ]], + [[ + pdcch-BlindDetection SetupRelease { PDCCH-BlindDetection } OPTIONAL -- Need M + ]], + [[ + dcp-Config-r16 SetupRelease { DCP-Config-r16 } OPTIONAL, -- Need M + harq-ACK-SpatialBundlingPUCCH-secondaryPUCCHgroup-r16 ENUMERATED {enabled, disabled} OPTIONAL, -- Cond twoPUCCHgroup + harq-ACK-SpatialBundlingPUSCH-secondaryPUCCHgroup-r16 ENUMERATED {enabled, disabled} OPTIONAL, -- Cond twoPUCCHgroup + pdsch-HARQ-ACK-Codebook-secondaryPUCCHgroup-r16 ENUMERATED {semiStatic, dynamic} OPTIONAL, -- Cond twoPUCCHgroup + p-NR-FR2-r16 P-Max OPTIONAL, -- Need R + p-UE-FR2-r16 P-Max OPTIONAL, -- Cond MCG-Only + nrdc-PCmode-FR1-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, -- Cond MCG-Only + nrdc-PCmode-FR2-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, -- Cond MCG-Only + pdsch-HARQ-ACK-Codebook-r16 ENUMERATED {enhancedDynamic} OPTIONAL, -- Need R + nfi-TotalDAI-Included-r16 ENUMERATED {true} OPTIONAL, -- Need R + ul-TotalDAI-Included-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedback-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedbackNDI-r16 ENUMERATED {true} OPTIONAL, -- Need R + pdsch-HARQ-ACK-OneShotFeedbackCBG-r16 ENUMERATED {true} OPTIONAL, -- Need R + downlinkAssignmentIndexDCI-0-2-r16 ENUMERATED { enabled } OPTIONAL, -- Need S + downlinkAssignmentIndexDCI-1-2-r16 ENUMERATED {n1, n2, n4} OPTIONAL, -- Need S + pdsch-HARQ-ACK-CodebookList-r16 SetupRelease {PDSCH-HARQ-ACK-CodebookList-r16} OPTIONAL, -- Need M + ackNackFeedbackMode-r16 ENUMERATED {joint, separate} OPTIONAL, -- Need R + pdcch-BlindDetectionCA-CombIndicator-r16 SetupRelease { PDCCH-BlindDetectionCA-CombIndicator-r16 } OPTIONAL, -- Need M + pdcch-BlindDetection2-r16 SetupRelease { PDCCH-BlindDetection2-r16 } OPTIONAL, -- Need M + pdcch-BlindDetection3-r16 SetupRelease { PDCCH-BlindDetection3-r16 } OPTIONAL, -- Need M + bdFactorR-r16 ENUMERATED {n1} OPTIONAL -- Need R + ]] +} + +PDCCH-BlindDetection ::= INTEGER (1..15) + +DCP-Config-r16 ::= SEQUENCE { + ps-RNTI-r16 RNTI-Value, + ps-Offset-r16 INTEGER (1..120), + sizeDCI-2-6-r16 INTEGER (1..maxDCI-2-6-Size-r16), + ps-PositionDCI-2-6-r16 INTEGER (0..maxDCI-2-6-Size-1-r16), + ps-WakeUp-r16 ENUMERATED {true} OPTIONAL, -- Need S + ps-TransmitPeriodicL1-RSRP-r16 ENUMERATED {true} OPTIONAL, -- Need S + ps-TransmitOtherPeriodicCSI-r16 ENUMERATED {true} OPTIONAL -- Need S +} + +PDSCH-HARQ-ACK-CodebookList-r16 ::= SEQUENCE (SIZE (1..2)) OF ENUMERATED {semiStatic, dynamic} + +PDCCH-BlindDetectionCA-CombIndicator-r16 ::= SEQUENCE { + pdcch-BlindDetectionCA1-r16 INTEGER (1..15), + pdcch-BlindDetectionCA2-r16 INTEGER (1..15) +} + +PDCCH-BlindDetection2-r16 ::= INTEGER (1..15) + +PDCCH-BlindDetection3-r16 ::= INTEGER (1..15) + +-- TAG-PHYSICALCELLGROUPCONFIG-STOP +-- TAG-PLMN-IDENTITY-START + +PLMN-Identity ::= SEQUENCE { + mcc MCC OPTIONAL, -- Cond MCC + mnc MNC +} + +MCC ::= SEQUENCE (SIZE (3)) OF MCC-MNC-Digit + +MNC ::= SEQUENCE (SIZE (2..3)) OF MCC-MNC-Digit + +MCC-MNC-Digit ::= INTEGER (0..9) + +-- TAG-PLMN-IDENTITY-STOP +-- TAG-PLMN-IDENTITYINFOLIST-START + +PLMN-IdentityInfoList ::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-IdentityInfo + +PLMN-IdentityInfo ::= SEQUENCE { + plmn-IdentityList SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity, + trackingAreaCode TrackingAreaCode OPTIONAL, -- Need R + ranac RAN-AreaCode OPTIONAL, -- Need R + cellIdentity CellIdentity, + cellReservedForOperatorUse ENUMERATED {reserved, notReserved}, + ..., + [[ + iab-Support-r16 ENUMERATED {true} OPTIONAL -- Need S + ]] +} +-- TAG-PLMN-IDENTITYINFOLIST-STOP +-- TAG-PLMNIDENTITYLIST2-START + +PLMN-IdentityList2-r16 ::= SEQUENCE (SIZE (1..16)) OF PLMN-Identity + +-- TAG-PLMNIDENTITYLIST2-STOP +-- TAG-PRB-ID-START + +PRB-Id ::= INTEGER (0..maxNrofPhysicalResourceBlocks-1) + +-- TAG-PRB-ID-STOP +-- TAG-PTRS-DOWNLINKCONFIG-START + +PTRS-DownlinkConfig ::= SEQUENCE { + frequencyDensity SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need S + timeDensity SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need S + epre-Ratio INTEGER (0..3) OPTIONAL, -- Need S + resourceElementOffset ENUMERATED { offset01, offset10, offset11 } OPTIONAL, -- Need S + ..., + [[ + maxNrofPorts-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + ]] + +} + +-- TAG-PTRS-DOWNLINKCONFIG-STOP +-- TAG-PTRS-UPLINKCONFIG-START + +PTRS-UplinkConfig ::= SEQUENCE { + transformPrecoderDisabled SEQUENCE { + frequencyDensity SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need S + timeDensity SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need S + maxNrofPorts ENUMERATED {n1, n2}, + resourceElementOffset ENUMERATED {offset01, offset10, offset11 } OPTIONAL, -- Need S + ptrs-Power ENUMERATED {p00, p01, p10, p11} + } OPTIONAL, -- Need R + transformPrecoderEnabled SEQUENCE { + sampleDensity SEQUENCE (SIZE (5)) OF INTEGER (1..276), + timeDensityTransformPrecoding ENUMERATED {d2} OPTIONAL -- Need S + } OPTIONAL, -- Need R + ... +} + +-- TAG-PTRS-UPLINKCONFIG-STOP +-- TAG-PUCCH-CONFIG-START + +PUCCH-Config ::= SEQUENCE { + resourceSetToAddModList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceSets)) OF PUCCH-ResourceSet OPTIONAL, -- Need N + resourceSetToReleaseList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceSets)) OF PUCCH-ResourceSetId OPTIONAL, -- Need N + resourceToAddModList SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-Resource OPTIONAL, -- Need N + resourceToReleaseList SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-ResourceId OPTIONAL, -- Need N + format1 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format2 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format3 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + format4 SetupRelease { PUCCH-FormatConfig } OPTIONAL, -- Need M + schedulingRequestResourceToAddModList SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceConfig + OPTIONAL, -- Need N + schedulingRequestResourceToReleaseList SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceId + OPTIONAL, -- Need N + multi-CSI-PUCCH-ResourceList SEQUENCE (SIZE (1..2)) OF PUCCH-ResourceId OPTIONAL, -- Need M + dl-DataToUL-ACK SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) OPTIONAL, -- Need M + spatialRelationInfoToAddModList SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos)) OF PUCCH-SpatialRelationInfo + OPTIONAL, -- Need N + spatialRelationInfoToReleaseList SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos)) OF PUCCH-SpatialRelationInfoId + OPTIONAL, -- Need N + pucch-PowerControl PUCCH-PowerControl OPTIONAL, -- Need M + ..., + [[ + resourceToAddModListExt-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-Resources)) OF PUCCH-ResourceExt-r16 OPTIONAL, -- Need N + dl-DataToUL-ACK-r16 SetupRelease { DL-DataToUL-ACK-r16 } OPTIONAL, -- Need M + ul-AccessConfigListDCI-1-1-r16 SetupRelease { UL-AccessConfigListDCI-1-1-r16 } OPTIONAL, -- Need M + subslotLengthForPUCCH-r16 CHOICE { + normalCP-r16 ENUMERATED {n2,n7}, + extendedCP-r16 ENUMERATED {n2,n6} + } OPTIONAL, -- Need R + dl-DataToUL-ACK-DCI-1-2-r16 SetupRelease { DL-DataToUL-ACK-DCI-1-2-r16} OPTIONAL, -- Need M + numberOfBitsForPUCCH-ResourceIndicatorDCI-1-2-r16 INTEGER (0..3) OPTIONAL, -- Need R + dmrs-UplinkTransformPrecodingPUCCH-r16 ENUMERATED {enabled} OPTIONAL, -- Cond PI2-BPSK + spatialRelationInfoToAddModListSizeExt-v1610 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfosDiff-r16)) OF PUCCH-SpatialRelationInfo + OPTIONAL, -- Need N + spatialRelationInfoToReleaseListSizeExt-v1610 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfosDiff-r16)) OF PUCCH-SpatialRelationInfoId + OPTIONAL, -- Need N + spatialRelationInfoToAddModListExt-v1610 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos-r16)) OF PUCCH-SpatialRelationInfoExt-r16 + OPTIONAL, -- Need N + spatialRelationInfoToReleaseListExt-v1610 SEQUENCE (SIZE (1..maxNrofSpatialRelationInfos-r16)) OF + PUCCH-SpatialRelationInfoId-r16 OPTIONAL, -- Need N + resourceGroupToAddModList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceGroups-r16)) OF PUCCH-ResourceGroup-r16 + OPTIONAL, -- Need N + resourceGroupToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourceGroups-r16)) OF PUCCH-ResourceGroupId-r16 + OPTIONAL, -- Need N + sps-PUCCH-AN-List-r16 SetupRelease { SPS-PUCCH-AN-List-r16 } OPTIONAL, -- Need M + schedulingRequestResourceToAddModListExt-v1610 SEQUENCE (SIZE (1..maxNrofSR-Resources)) OF SchedulingRequestResourceConfigExt-v1610 + OPTIONAL -- Need N + ]] +} + +PUCCH-FormatConfig ::= SEQUENCE { + interslotFrequencyHopping ENUMERATED {enabled} OPTIONAL, -- Need R + additionalDMRS ENUMERATED {true} OPTIONAL, -- Need R + maxCodeRate PUCCH-MaxCodeRate OPTIONAL, -- Need R + nrofSlots ENUMERATED {n2,n4,n8} OPTIONAL, -- Need S + pi2BPSK ENUMERATED {enabled} OPTIONAL, -- Need R + simultaneousHARQ-ACK-CSI ENUMERATED {true} OPTIONAL -- Need R +} + +PUCCH-MaxCodeRate ::= ENUMERATED {zeroDot08, zeroDot15, zeroDot25, zeroDot35, zeroDot45, zeroDot60, zeroDot80} + +-- A set with one or more PUCCH resources +PUCCH-ResourceSet ::= SEQUENCE { + pucch-ResourceSetId PUCCH-ResourceSetId, + resourceList SEQUENCE (SIZE (1..maxNrofPUCCH-ResourcesPerSet)) OF PUCCH-ResourceId, + maxPayloadSize INTEGER (4..256) OPTIONAL -- Need R +} + +PUCCH-ResourceSetId ::= INTEGER (0..maxNrofPUCCH-ResourceSets-1) + +PUCCH-Resource ::= SEQUENCE { + pucch-ResourceId PUCCH-ResourceId, + startingPRB PRB-Id, + intraSlotFrequencyHopping ENUMERATED { enabled } OPTIONAL, -- Need R + secondHopPRB PRB-Id OPTIONAL, -- Need R + format CHOICE { + format0 PUCCH-format0, + format1 PUCCH-format1, + format2 PUCCH-format2, + format3 PUCCH-format3, + format4 PUCCH-format4 + } +} + +PUCCH-ResourceExt-r16 ::= SEQUENCE { + interlaceAllocation-r16 SEQUENCE { + rb-SetIndex INTEGER (0..4), + interlace0 CHOICE { + scs15 INTEGER (0..9), + scs30 INTEGER (0..4) + } + } OPTIONAL, --Need R + formatExt-v1610 CHOICE { + interlace1-v1610 INTEGER (0..9), + occ-v1610 SEQUENCE { + occ-Length-v1610 ENUMERATED {n2,n4} OPTIONAL, -- Need M + occ-Index-v1610 ENUMERATED {n0,n1,n2,n3} OPTIONAL -- Need M + } + } OPTIONAL, -- Need R + ... +} + +PUCCH-ResourceId ::= INTEGER (0..maxNrofPUCCH-Resources-1) + + +PUCCH-format0 ::= SEQUENCE { + initialCyclicShift INTEGER(0..11), + nrofSymbols INTEGER (1..2), + startingSymbolIndex INTEGER(0..13) +} + +PUCCH-format1 ::= SEQUENCE { + initialCyclicShift INTEGER(0..11), + nrofSymbols INTEGER (4..14), + startingSymbolIndex INTEGER(0..10), + timeDomainOCC INTEGER(0..6) +} + +PUCCH-format2 ::= SEQUENCE { + nrofPRBs INTEGER (1..16), + nrofSymbols INTEGER (1..2), + startingSymbolIndex INTEGER(0..13) +} + +PUCCH-format3 ::= SEQUENCE { + nrofPRBs INTEGER (1..16), + nrofSymbols INTEGER (4..14), + startingSymbolIndex INTEGER(0..10) +} + +PUCCH-format4 ::= SEQUENCE { + nrofSymbols INTEGER (4..14), + occ-Length ENUMERATED {n2,n4}, + occ-Index ENUMERATED {n0,n1,n2,n3}, + startingSymbolIndex INTEGER(0..10) +} + +PUCCH-ResourceGroup-r16 ::= SEQUENCE { + pucch-ResourceGroupId-r16 PUCCH-ResourceGroupId-r16, + resourcePerGroupList-r16 SEQUENCE (SIZE (1..maxNrofPUCCH-ResourcesPerGroup-r16)) OF PUCCH-ResourceId +} + +PUCCH-ResourceGroupId-r16 ::= INTEGER (0..maxNrofPUCCH-ResourceGroups-1-r16) + +DL-DataToUL-ACK-r16 ::= SEQUENCE (SIZE (1..8)) OF INTEGER (-1..15) + +DL-DataToUL-ACK-DCI-1-2-r16 ::= SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) + +UL-AccessConfigListDCI-1-1-r16 ::= SEQUENCE (SIZE (1..16)) OF INTEGER (0..15) + +-- TAG-PUCCH-CONFIG-STOP +-- TAG-PUCCH-CONFIGCOMMON-START + +PUCCH-ConfigCommon ::= SEQUENCE { + pucch-ResourceCommon INTEGER (0..15) OPTIONAL, -- Cond InitialBWP-Only + pucch-GroupHopping ENUMERATED { neither, enable, disable }, + hoppingId INTEGER (0..1023) OPTIONAL, -- Need R + p0-nominal INTEGER (-202..24) OPTIONAL, -- Need R + ... +} + +-- TAG-PUCCH-CONFIGCOMMON-STOP +-- TAG-PUCCH-CONFIGURATIONLIST-START + +PUCCH-ConfigurationList-r16 ::= SEQUENCE (SIZE (1..2)) OF PUCCH-Config + +-- TAG-PUCCH-CONFIGURATIONLIST-STOP +-- TAG-PUCCH-PATHLOSSREFERENCERS-ID-START + +PUCCH-PathlossReferenceRS-Id ::= INTEGER (0..maxNrofPUCCH-PathlossReferenceRSs-1) + +PUCCH-PathlossReferenceRS-Id-v1610 ::= INTEGER (maxNrofPUCCH-PathlossReferenceRSs..maxNrofPUCCH-PathlossReferenceRSs-1-r16) + +-- TAG-PUCCH-PATHLOSSREFERENCERS-ID-STOP +-- TAG-PUCCH-POWERCONTROL-START +PUCCH-PowerControl ::= SEQUENCE { + deltaF-PUCCH-f0 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f1 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f2 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f3 INTEGER (-16..15) OPTIONAL, -- Need R + deltaF-PUCCH-f4 INTEGER (-16..15) OPTIONAL, -- Need R + p0-Set SEQUENCE (SIZE (1..maxNrofPUCCH-P0-PerSet)) OF P0-PUCCH OPTIONAL, -- Need M + pathlossReferenceRSs SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSs)) OF PUCCH-PathlossReferenceRS + OPTIONAL, -- Need M + twoPUCCH-PC-AdjustmentStates ENUMERATED {twoStates} OPTIONAL, -- Need S + ..., + [[ + pathlossReferenceRSs-v1610 SetupRelease { PathlossReferenceRSs-v1610 } OPTIONAL -- Need M + ]] +} + +P0-PUCCH ::= SEQUENCE { + p0-PUCCH-Id P0-PUCCH-Id, + p0-PUCCH-Value INTEGER (-16..15) +} + +P0-PUCCH-Id ::= INTEGER (1..8) + +PathlossReferenceRSs-v1610 ::= SEQUENCE (SIZE (1..maxNrofPUCCH-PathlossReferenceRSsDiff-r16)) OF PUCCH-PathlossReferenceRS-r16 + +PUCCH-PathlossReferenceRS ::= SEQUENCE { + pucch-PathlossReferenceRS-Id PUCCH-PathlossReferenceRS-Id, + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + } +} + +PUCCH-PathlossReferenceRS-r16 ::= SEQUENCE { + pucch-PathlossReferenceRS-Id-r16 PUCCH-PathlossReferenceRS-Id-v1610, + referenceSignal-r16 CHOICE { + ssb-Index-r16 SSB-Index, + csi-RS-Index-r16 NZP-CSI-RS-ResourceId + } +} + +-- TAG-PUCCH-POWERCONTROL-STOP +-- TAG-PUCCH-SPATIALRELATIONINFO-START + +PUCCH-SpatialRelationInfo ::= SEQUENCE { + pucch-SpatialRelationInfoId PUCCH-SpatialRelationInfoId, + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId, + srs PUCCH-SRS + }, + pucch-PathlossReferenceRS-Id PUCCH-PathlossReferenceRS-Id, + p0-PUCCH-Id P0-PUCCH-Id, + closedLoopIndex ENUMERATED { i0, i1 } +} + +PUCCH-SpatialRelationInfoExt-r16 ::= SEQUENCE { + pucch-SpatialRelationInfoId-v1610 PUCCH-SpatialRelationInfoId-v1610 OPTIONAL, -- Cond SetupOnly + pucch-PathlossReferenceRS-Id-v1610 PUCCH-PathlossReferenceRS-Id-v1610 OPTIONAL, --Need R + ... +} + +PUCCH-SRS ::= SEQUENCE { + resource SRS-ResourceId, + uplinkBWP BWP-Id +} +-- TAG-PUCCH-SPATIALRELATIONINFO-STOP +-- TAG-PUCCH-SPATIALRELATIONINFO-START + +PUCCH-SpatialRelationInfoId ::= INTEGER (1..maxNrofSpatialRelationInfos) + +PUCCH-SpatialRelationInfoId-r16 ::= INTEGER (1..maxNrofSpatialRelationInfos-r16) + +PUCCH-SpatialRelationInfoId-v1610::= INTEGER (maxNrofSpatialRelationInfos-plus-1..maxNrofSpatialRelationInfos-r16) + +-- TAG-PUCCH-SPATIALRELATIONINFO-STOP +-- TAG-PUCCH-TPC-COMMANDCONFIG-START + +PUCCH-TPC-CommandConfig ::= SEQUENCE { + tpc-IndexPCell INTEGER (1..15) OPTIONAL, -- Cond PDCCH-OfSpcell + tpc-IndexPUCCH-SCell INTEGER (1..15) OPTIONAL, -- Cond PDCCH-ofSpCellOrPUCCH-SCell + ... +} + +-- TAG-PUCCH-TPC-COMMANDCONFIG-STOP +-- TAG-PUSCH-CONFIG-START + +PUSCH-Config ::= SEQUENCE { + dataScramblingIdentityPUSCH INTEGER (0..1023) OPTIONAL, -- Need S + txConfig ENUMERATED {codebook, nonCodebook} OPTIONAL, -- Need S + dmrs-UplinkForPUSCH-MappingTypeA SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + dmrs-UplinkForPUSCH-MappingTypeB SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + pusch-PowerControl PUSCH-PowerControl OPTIONAL, -- Need M + frequencyHopping ENUMERATED {intraSlot, interSlot} OPTIONAL, -- Need S + frequencyHoppingOffsetLists SEQUENCE (SIZE (1..4)) OF INTEGER (1.. maxNrofPhysicalResourceBlocks-1) + OPTIONAL, -- Need M + resourceAllocation ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch}, + pusch-TimeDomainAllocationList SetupRelease { PUSCH-TimeDomainResourceAllocationList } OPTIONAL, -- Need M + pusch-AggregationFactor ENUMERATED { n2, n4, n8 } OPTIONAL, -- Need S + mcs-Table ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoder ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + transformPrecoder ENUMERATED {enabled, disabled} OPTIONAL, -- Need S + codebookSubset ENUMERATED {fullyAndPartialAndNonCoherent, partialAndNonCoherent,nonCoherent} + OPTIONAL, -- Cond codebookBased + maxRank INTEGER (1..4) OPTIONAL, -- Cond codebookBased + rbg-Size ENUMERATED { config2} OPTIONAL, -- Need S + uci-OnPUSCH SetupRelease { UCI-OnPUSCH} OPTIONAL, -- Need M + tp-pi2BPSK ENUMERATED {enabled} OPTIONAL, -- Need S + ..., + [[ + minimumSchedulingOffsetK2-r16 SetupRelease { MinSchedulingOffsetK2-Values-r16 } OPTIONAL, -- Need M + ul-AccessConfigListDCI-0-1-r16 SetupRelease { UL-AccessConfigListDCI-0-1-r16 } OPTIONAL, -- Need M + -- Start of the parameters for DCI format 0_2 introduced in V16.1.0 + harq-ProcessNumberSizeDCI-0-2-r16 INTEGER (0..4) OPTIONAL, -- Need R + dmrs-SequenceInitializationDCI-0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + numberOfBitsForRV-DCI-0-2-r16 INTEGER (0..2) OPTIONAL, -- Need R + antennaPortsFieldPresenceDCI-0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + dmrs-UplinkForPUSCH-MappingTypeA-DCI-0-2-r16 SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + dmrs-UplinkForPUSCH-MappingTypeB-DCI-0-2-r16 SetupRelease { DMRS-UplinkConfig } OPTIONAL, -- Need M + frequencyHoppingDCI-0-2-r16 CHOICE { + pusch-RepTypeA ENUMERATED {intraSlot, interSlot}, + pusch-RepTypeB ENUMERATED {interRepetition, interSlot} + } OPTIONAL, -- Need S + frequencyHoppingOffsetListsDCI-0-2-r16 SetupRelease { FrequencyHoppingOffsetListsDCI-0-2-r16} OPTIONAL, -- Need M + codebookSubsetDCI-0-2-r16 ENUMERATED {fullyAndPartialAndNonCoherent, partialAndNonCoherent,nonCoherent} + OPTIONAL, -- Cond codebookBased + invalidSymbolPatternIndicatorDCI-0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + maxRankDCI-0-2-r16 INTEGER (1..4) OPTIONAL, -- Cond codebookBased + mcs-TableDCI-0-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + mcs-TableTransformPrecoderDCI-0-2-r16 ENUMERATED {qam256, qam64LowSE} OPTIONAL, -- Need S + priorityIndicatorDCI-0-2-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + pusch-RepTypeIndicatorDCI-0-2-r16 ENUMERATED { pusch-RepTypeA, pusch-RepTypeB} OPTIONAL, -- Need R + resourceAllocationDCI-0-2-r16 ENUMERATED { resourceAllocationType0, resourceAllocationType1, dynamicSwitch} + OPTIONAL, -- Need M + resourceAllocationType1GranularityDCI-0-2-r16 ENUMERATED { n2,n4,n8,n16 } OPTIONAL, -- Need S + uci-OnPUSCH-ListDCI-0-2-r16 SetupRelease { UCI-OnPUSCH-ListDCI-0-2-r16} OPTIONAL, -- Need M + pusch-TimeDomainAllocationListDCI-0-2-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + -- End of the parameters for DCI format 0_2 introduced in V16.1.0 + -- Start of the parameters for DCI format 0_1 introduced in V16.1.0 + pusch-TimeDomainAllocationListDCI-0-1-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + invalidSymbolPatternIndicatorDCI-0-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + priorityIndicatorDCI-0-1-r16 ENUMERATED {enabled} OPTIONAL, -- Need S + pusch-RepTypeIndicatorDCI-0-1-r16 ENUMERATED { pusch-RepTypeA, pusch-RepTypeB} OPTIONAL, -- Need R + frequencyHoppingDCI-0-1-r16 ENUMERATED {interRepetition, interSlot} OPTIONAL, -- Cond RepTypeB + uci-OnPUSCH-ListDCI-0-1-r16 SetupRelease { UCI-OnPUSCH-ListDCI-0-1-r16 } OPTIONAL, -- Need M + -- End of the parameters for DCI format 0_1 introduced in V16.1.0 + invalidSymbolPattern-r16 InvalidSymbolPattern-r16 OPTIONAL, -- Need S + pusch-PowerControl-v1610 SetupRelease {PUSCH-PowerControl-v1610} OPTIONAL, -- Need M + ul-FullPowerTransmission-r16 ENUMERATED {fullpower, fullpowerMode1, fullpowerMode2} OPTIONAL, -- Need R + pusch-TimeDomainAllocationListForMultiPUSCH-r16 SetupRelease { PUSCH-TimeDomainResourceAllocationList-r16 } + OPTIONAL, -- Need M + numberOfInvalidSymbolsForDL-UL-Switching-r16 INTEGER (1..4) OPTIONAL -- Cond RepTypeB2 + ]] +} + +UCI-OnPUSCH ::= SEQUENCE { + betaOffsets CHOICE { + dynamic SEQUENCE (SIZE (4)) OF BetaOffsets, + semiStatic BetaOffsets + } OPTIONAL, -- Need M + scaling ENUMERATED { f0p5, f0p65, f0p8, f1 } +} + +MinSchedulingOffsetK2-Values-r16 ::= SEQUENCE (SIZE (1..maxNrOfMinSchedulingOffsetValues-r16)) OF INTEGER (0..maxK2-SchedulingOffset-r16) + +UCI-OnPUSCH-DCI-0-2-r16 ::= SEQUENCE { + betaOffsetsDCI-0-2-r16 CHOICE { + dynamicDCI-0-2-r16 CHOICE { + oneBit-r16 SEQUENCE (SIZE (2)) OF BetaOffsets, + twoBits-r16 SEQUENCE (SIZE (4)) OF BetaOffsets + }, + semiStaticDCI-0-2-r16 BetaOffsets + } OPTIONAL, -- Need M + scalingDCI-0-2-r16 ENUMERATED { f0p5, f0p65, f0p8, f1 } +} + +FrequencyHoppingOffsetListsDCI-0-2-r16 ::= SEQUENCE (SIZE (1..4)) OF INTEGER (1.. maxNrofPhysicalResourceBlocks-1) + +UCI-OnPUSCH-ListDCI-0-2-r16 ::= SEQUENCE (SIZE (1..2)) OF UCI-OnPUSCH-DCI-0-2-r16 + +UCI-OnPUSCH-ListDCI-0-1-r16 ::= SEQUENCE (SIZE (1..2)) OF UCI-OnPUSCH + +UL-AccessConfigListDCI-0-1-r16 ::= SEQUENCE (SIZE (1..64)) OF INTEGER (0..63) + +-- TAG-PUSCH-CONFIG-STOP +-- TAG-PUSCH-CONFIGCOMMON-START + +PUSCH-ConfigCommon ::= SEQUENCE { + groupHoppingEnabledTransformPrecoding ENUMERATED {enabled} OPTIONAL, -- Need R + pusch-TimeDomainAllocationList PUSCH-TimeDomainResourceAllocationList OPTIONAL, -- Need R + msg3-DeltaPreamble INTEGER (-1..6) OPTIONAL, -- Need R + p0-NominalWithGrant INTEGER (-202..24) OPTIONAL, -- Need R + ... +} + +-- TAG-PUSCH-CONFIGCOMMON-STOP +-- TAG-PUSCH-POWERCONTROL-START + +PUSCH-PowerControl ::= SEQUENCE { + tpc-Accumulation ENUMERATED { disabled } OPTIONAL, -- Need S + msg3-Alpha Alpha OPTIONAL, -- Need S + p0-NominalWithoutGrant INTEGER (-202..24) OPTIONAL, -- Need M + p0-AlphaSets SEQUENCE (SIZE (1..maxNrofP0-PUSCH-AlphaSets)) OF P0-PUSCH-AlphaSet OPTIONAL, -- Need M + pathlossReferenceRSToAddModList SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSs)) OF PUSCH-PathlossReferenceRS + OPTIONAL, -- Need N + pathlossReferenceRSToReleaseList SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSs)) OF PUSCH-PathlossReferenceRS-Id + OPTIONAL, -- Need N + twoPUSCH-PC-AdjustmentStates ENUMERATED {twoStates} OPTIONAL, -- Need S + deltaMCS ENUMERATED {enabled} OPTIONAL, -- Need S + sri-PUSCH-MappingToAddModList SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF SRI-PUSCH-PowerControl + OPTIONAL, -- Need N + sri-PUSCH-MappingToReleaseList SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF SRI-PUSCH-PowerControlId + OPTIONAL -- Need N +} + +P0-PUSCH-AlphaSet ::= SEQUENCE { + p0-PUSCH-AlphaSetId P0-PUSCH-AlphaSetId, + p0 INTEGER (-16..15) OPTIONAL, -- Need S + alpha Alpha OPTIONAL -- Need S +} + +P0-PUSCH-AlphaSetId ::= INTEGER (0..maxNrofP0-PUSCH-AlphaSets-1) + +PUSCH-PathlossReferenceRS ::= SEQUENCE { + pusch-PathlossReferenceRS-Id PUSCH-PathlossReferenceRS-Id, + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + } +} + +PUSCH-PathlossReferenceRS-r16 ::= SEQUENCE { + pusch-PathlossReferenceRS-Id-r16 PUSCH-PathlossReferenceRS-Id-v1610, + referenceSignal-r16 CHOICE { + ssb-Index-r16 SSB-Index, + csi-RS-Index-r16 NZP-CSI-RS-ResourceId + } +} + +PUSCH-PathlossReferenceRS-Id ::= INTEGER (0..maxNrofPUSCH-PathlossReferenceRSs-1) + +PUSCH-PathlossReferenceRS-Id-v1610 ::= INTEGER (maxNrofPUSCH-PathlossReferenceRSs..maxNrofPUSCH-PathlossReferenceRSs-1-r16) + +SRI-PUSCH-PowerControl ::= SEQUENCE { + sri-PUSCH-PowerControlId SRI-PUSCH-PowerControlId, + sri-PUSCH-PathlossReferenceRS-Id PUSCH-PathlossReferenceRS-Id, + sri-P0-PUSCH-AlphaSetId P0-PUSCH-AlphaSetId, + sri-PUSCH-ClosedLoopIndex ENUMERATED { i0, i1 } +} + +SRI-PUSCH-PowerControlId ::= INTEGER (0..maxNrofSRI-PUSCH-Mappings-1) + +PUSCH-PowerControl-v1610 ::= SEQUENCE { + pathlossReferenceRSToAddModListSizeExt-v1610 SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSsDiff-r16)) OF PUSCH-PathlossReferenceRS-r16 + OPTIONAL, -- Need N + pathlossReferenceRSToReleaseListSizeExt-v1610 SEQUENCE (SIZE (1..maxNrofPUSCH-PathlossReferenceRSsDiff-r16)) OF PUSCH-PathlossReferenceRS-Id-v1610 + OPTIONAL, -- Need N + p0-PUSCH-SetList-r16 SEQUENCE (SIZE (1..maxNrofSRI-PUSCH-Mappings)) OF P0-PUSCH-Set-r16 OPTIONAL, -- Need R + olpc-ParameterSet SEQUENCE { + olpc-ParameterSetDCI-0-1-r16 INTEGER (1..2) OPTIONAL, -- Need R + olpc-ParameterSetDCI-0-2-r16 INTEGER (1..2) OPTIONAL -- Need R + } OPTIONAL, -- Need M + ... +} + +P0-PUSCH-Set-r16 ::= SEQUENCE { + p0-PUSCH-SetId-r16 P0-PUSCH-SetId-r16, + p0-List-r16 SEQUENCE (SIZE (1..maxNrofP0-PUSCH-Set-r16)) OF P0-PUSCH-r16 OPTIONAL, -- Need R + ... +} + +P0-PUSCH-SetId-r16 ::= INTEGER (0..maxNrofSRI-PUSCH-Mappings-1) + +P0-PUSCH-r16 ::= INTEGER (-16..15) + +-- TAG-PUSCH-POWERCONTROL-STOP +-- TAG-PUSCH-SERVINGCELLCONFIG-START + +PUSCH-ServingCellConfig ::= SEQUENCE { + codeBlockGroupTransmission SetupRelease { PUSCH-CodeBlockGroupTransmission } OPTIONAL, -- Need M + rateMatching ENUMERATED {limitedBufferRM} OPTIONAL, -- Need S + xOverhead ENUMERATED {xoh6, xoh12, xoh18} OPTIONAL, -- Need S + ..., + [[ + maxMIMO-Layers INTEGER (1..4) OPTIONAL, -- Need M + processingType2Enabled BOOLEAN OPTIONAL -- Need M + ]], + [[ + maxMIMO-LayersDCI-0-2-r16 SetupRelease { MaxMIMO-LayersDCI-0-2-r16} OPTIONAL -- Need M + ]] +} + +PUSCH-CodeBlockGroupTransmission ::= SEQUENCE { + maxCodeBlockGroupsPerTransportBlock ENUMERATED {n2, n4, n6, n8}, + ... +} + +MaxMIMO-LayersDCI-0-2-r16 ::= INTEGER (1..4) + +-- TAG-PUSCH-SERVINGCELLCONFIG-STOP +-- TAG-PUSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-START + +PUSCH-TimeDomainResourceAllocationList ::= SEQUENCE (SIZE(1..maxNrofUL-Allocations)) OF PUSCH-TimeDomainResourceAllocation + +PUSCH-TimeDomainResourceAllocation ::= SEQUENCE { + k2 INTEGER(0..32) OPTIONAL, -- Need S + mappingType ENUMERATED {typeA, typeB}, + startSymbolAndLength INTEGER (0..127) +} + +PUSCH-TimeDomainResourceAllocationList-r16 ::= SEQUENCE (SIZE(1..maxNrofUL-Allocations-r16)) OF PUSCH-TimeDomainResourceAllocation-r16 + +PUSCH-TimeDomainResourceAllocation-r16 ::= SEQUENCE { + k2-r16 INTEGER(0..32) OPTIONAL, -- Need S + puschAllocationList-r16 SEQUENCE (SIZE(1..maxNrofMultiplePUSCHs-r16)) OF PUSCH-Allocation-r16, +... +} + +PUSCH-Allocation-r16 ::= SEQUENCE { + mappingType-r16 ENUMERATED {typeA, typeB} OPTIONAL, -- Cond NotFormat01-02-Or-TypeA + startSymbolAndLength-r16 INTEGER (0..127) OPTIONAL, -- Cond NotFormat01-02-Or-TypeA + startSymbol-r16 INTEGER (0..13) OPTIONAL, -- Cond RepTypeB + length-r16 INTEGER (1..14) OPTIONAL, -- Cond RepTypeB + numberOfRepetitions-r16 ENUMERATED {n1, n2, n3, n4, n7, n8, n12, n16} OPTIONAL, -- Cond Format01-02 + ... +} + +-- TAG-PUSCH-TIMEDOMAINRESOURCEALLOCATIONLIST-STOP +-- TAG-PUSCH-TPC-COMMANDCONFIG-START + +PUSCH-TPC-CommandConfig ::= SEQUENCE { + tpc-Index INTEGER (1..15) OPTIONAL, -- Cond SUL + tpc-IndexSUL INTEGER (1..15) OPTIONAL, -- Cond SUL-Only + targetCell ServCellIndex OPTIONAL, -- Need S + ... +} + +-- TAG-PUSCH-TPC-COMMANDCONFIG-STOP +-- TAG-Q-OFFSETRANGE-START + +Q-OffsetRange ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-Q-OFFSETRANGE-STOP +-- TAG-Q-QUALMIN-START + +Q-QualMin ::= INTEGER (-43..-12) + +-- TAG-Q-QUALMIN-STOP +-- TAG-Q-RXLEVMIN-START + +Q-RxLevMin ::= INTEGER (-70..-22) + +-- TAG-Q-RXLEVMIN-STOP +-- TAG-QUANTITYCONFIG-START + + +QuantityConfig ::= SEQUENCE { + quantityConfigNR-List SEQUENCE (SIZE (1..maxNrofQuantityConfig)) OF QuantityConfigNR OPTIONAL, -- Need M + ..., + [[ + quantityConfigEUTRA FilterConfig OPTIONAL -- Need M + ]], + [[ + quantityConfigUTRA-FDD-r16 QuantityConfigUTRA-FDD-r16 OPTIONAL, -- Need M + quantityConfigCLI-r16 FilterConfigCLI-r16 OPTIONAL -- Need M + ]] +} + +QuantityConfigNR::= SEQUENCE { + quantityConfigCell QuantityConfigRS, + quantityConfigRS-Index QuantityConfigRS OPTIONAL -- Need M +} + +QuantityConfigRS ::= SEQUENCE { + ssb-FilterConfig FilterConfig, + csi-RS-FilterConfig FilterConfig +} + +FilterConfig ::= SEQUENCE { + filterCoefficientRSRP FilterCoefficient DEFAULT fc4, + filterCoefficientRSRQ FilterCoefficient DEFAULT fc4, + filterCoefficientRS-SINR FilterCoefficient DEFAULT fc4 +} + +FilterConfigCLI-r16 ::= SEQUENCE { + filterCoefficientSRS-RSRP-r16 FilterCoefficient DEFAULT fc4, + filterCoefficientCLI-RSSI-r16 FilterCoefficient DEFAULT fc4 +} + +QuantityConfigUTRA-FDD-r16 ::= SEQUENCE { + filterCoefficientRSCP-r16 FilterCoefficient DEFAULT fc4, + filterCoefficientEcNO-r16 FilterCoefficient DEFAULT fc4 +} + +-- TAG-QUANTITYCONFIG-STOP +-- TAG-RACH-CONFIGCOMMON-START + +RACH-ConfigCommon ::= SEQUENCE { + rach-ConfigGeneric RACH-ConfigGeneric, + totalNumberOfRA-Preambles INTEGER (1..63) OPTIONAL, -- Need S + ssb-perRACH-OccasionAndCB-PreamblesPerSSB CHOICE { + oneEighth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneFourth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneHalf ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + one ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + two ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32}, + four INTEGER (1..16), + eight INTEGER (1..8), + sixteen INTEGER (1..4) + } OPTIONAL, -- Need M + + groupBconfigured SEQUENCE { + ra-Msg3SizeGroupA ENUMERATED {b56, b144, b208, b256, b282, b480, b640, + b800, b1000, b72, spare6, spare5,spare4, spare3, spare2, spare1}, + messagePowerOffsetGroupB ENUMERATED { minusinfinity, dB0, dB5, dB8, dB10, dB12, dB15, dB18}, + numberOfRA-PreamblesGroupA INTEGER (1..64) + } OPTIONAL, -- Need R + ra-ContentionResolutionTimer ENUMERATED { sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64}, + rsrp-ThresholdSSB RSRP-Range OPTIONAL, -- Need R + rsrp-ThresholdSSB-SUL RSRP-Range OPTIONAL, -- Cond SUL + prach-RootSequenceIndex CHOICE { + l839 INTEGER (0..837), + l139 INTEGER (0..137) + }, + msg1-SubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond L139 + restrictedSetConfig ENUMERATED {unrestrictedSet, restrictedSetTypeA, restrictedSetTypeB}, + msg3-transformPrecoder ENUMERATED {enabled} OPTIONAL, -- Need R + ..., + [[ + ra-PrioritizationForAccessIdentity-r16 SEQUENCE { + ra-Prioritization-r16 RA-Prioritization, + ra-PrioritizationForAI-r16 BIT STRING (SIZE (2)) + } OPTIONAL, -- Cond InitialBWP-Only + prach-RootSequenceIndex-r16 CHOICE { + l571 INTEGER (0..569), + l1151 INTEGER (0..1149) + } OPTIONAL -- Need R + ]] +} + +-- TAG-RACH-CONFIGCOMMON-STOP +-- TAG-RACH-CONFIGCOMMONTWOSTEPRA-START + +RACH-ConfigCommonTwoStepRA-r16 ::= SEQUENCE { + rach-ConfigGenericTwoStepRA-r16 RACH-ConfigGenericTwoStepRA-r16, + msgA-TotalNumberOfRA-Preambles-r16 INTEGER (1..63) OPTIONAL, -- Need S + msgA-SSB-PerRACH-OccasionAndCB-PreamblesPerSSB-r16 CHOICE { + oneEighth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneFourth ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + oneHalf ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + one ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32,n36,n40,n44,n48,n52,n56,n60,n64}, + two ENUMERATED {n4,n8,n12,n16,n20,n24,n28,n32}, + four INTEGER (1..16), + eight INTEGER (1..8), + sixteen INTEGER (1..4) + } OPTIONAL, -- Cond 2StepOnly + msgA-CB-PreamblesPerSSB-PerSharedRO-r16 INTEGER (1..60) OPTIONAL, -- Cond SharedRO + msgA-SSB-SharedRO-MaskIndex-r16 INTEGER (1..15) OPTIONAL, -- Need S + groupB-ConfiguredTwoStepRA-r16 GroupB-ConfiguredTwoStepRA-r16 OPTIONAL, -- Need S + msgA-PRACH-RootSequenceIndex-r16 CHOICE { + l839 INTEGER (0..837), + l139 INTEGER (0..137), + l571 INTEGER (0..569), + l1151 INTEGER (0..1149) + } OPTIONAL, -- Cond 2StepOnly + msgA-TransMax-r16 ENUMERATED {n1, n2, n4, n6, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Need R + msgA-RSRP-Threshold-r16 RSRP-Range OPTIONAL, -- Cond 2Step4Step + msgA-RSRP-ThresholdSSB-r16 RSRP-Range OPTIONAL, -- Need R + msgA-SubcarrierSpacing-r16 SubcarrierSpacing OPTIONAL, -- Cond 2StepOnlyL139 + msgA-RestrictedSetConfig-r16 ENUMERATED {unrestrictedSet, restrictedSetTypeA, + restrictedSetTypeB} OPTIONAL, -- Cond 2StepOnly + ra-PrioritizationForAccessIdentityTwoStep-r16 SEQUENCE { + ra-Prioritization-r16 RA-Prioritization, + ra-PrioritizationForAI-r16 BIT STRING (SIZE (2)) + } OPTIONAL, -- Cond InitialBWP-Only + ra-ContentionResolutionTimer-r16 ENUMERATED {sf8, sf16, sf24, sf32, sf40, sf48, sf56, sf64} OPTIONAL, -- Cond 2StepOnly + ... +} + +GroupB-ConfiguredTwoStepRA-r16 ::= SEQUENCE { + ra-MsgA-SizeGroupA ENUMERATED {b56, b144, b208, b256, b282, b480, b640, b800, + b1000, b72, spare6, spare5, spare4, spare3, spare2, spare1}, + messagePowerOffsetGroupB ENUMERATED {minusinfinity, dB0, dB5, dB8, dB10, dB12, dB15, dB18}, + numberOfRA-PreamblesGroupA INTEGER (1..64) +} + +-- TAG-RACH-CONFIGCOMMONTWOSTEPRA-STOP +-- TAG-RACH-CONFIGDEDICATED-START + + +RACH-ConfigDedicated ::= SEQUENCE { + cfra CFRA OPTIONAL, -- Need S + ra-Prioritization RA-Prioritization OPTIONAL, -- Need N + ..., + [[ + ra-PrioritizationTwoStep-r16 RA-Prioritization OPTIONAL, -- Need N + cfra-TwoStep-r16 CFRA-TwoStep-r16 OPTIONAL -- Need S + ]] +} + +CFRA ::= SEQUENCE { + occasions SEQUENCE { + rach-ConfigGeneric RACH-ConfigGeneric, + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, four, eight, sixteen} + OPTIONAL -- Cond Mandatory + } OPTIONAL, -- Need S + resources CHOICE { + ssb SEQUENCE { + ssb-ResourceList SEQUENCE (SIZE(1..maxRA-SSB-Resources)) OF CFRA-SSB-Resource, + ra-ssb-OccasionMaskIndex INTEGER (0..15) + }, + csirs SEQUENCE { + csirs-ResourceList SEQUENCE (SIZE(1..maxRA-CSIRS-Resources)) OF CFRA-CSIRS-Resource, + rsrp-ThresholdCSI-RS RSRP-Range + } + }, + ..., + [[ + totalNumberOfRA-Preambles INTEGER (1..63) OPTIONAL -- Cond Occasions + ]] +} + +CFRA-TwoStep-r16 ::= SEQUENCE { + occasionsTwoStepRA-r16 SEQUENCE { + rach-ConfigGenericTwoStepRA-r16 RACH-ConfigGenericTwoStepRA-r16, + ssb-PerRACH-OccasionTwoStepRA-r16 ENUMERATED {oneEighth, oneFourth, oneHalf, one, + two, four, eight, sixteen} + } OPTIONAL, -- Need S + msgA-CFRA-PUSCH-r16 MsgA-PUSCH-Resource-r16, + msgA-TransMax-r16 ENUMERATED {n1, n2, n4, n6, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Need S + resourcesTwoStep-r16 SEQUENCE { + ssb-ResourceList SEQUENCE (SIZE(1..maxRA-SSB-Resources)) OF CFRA-SSB-Resource, + ra-ssb-OccasionMaskIndex INTEGER (0..15) + }, + ... +} + +CFRA-SSB-Resource ::= SEQUENCE { + ssb SSB-Index, + ra-PreambleIndex INTEGER (0..63), + ..., + [[ + msgA-PUSCH-Resource-Index-r16 INTEGER (0..3071) OPTIONAL -- Cond 2StepCFRA + ]] + +} + +CFRA-CSIRS-Resource ::= SEQUENCE { + csi-RS CSI-RS-Index, + ra-OccasionList SEQUENCE (SIZE(1..maxRA-OccasionsPerCSIRS)) OF INTEGER (0..maxRA-Occasions-1), + ra-PreambleIndex INTEGER (0..63), + ... +} + +-- TAG-RACH-CONFIGDEDICATED-STOP +-- TAG-RACH-CONFIGGENERIC-START + +RACH-ConfigGeneric ::= SEQUENCE { + prach-ConfigurationIndex INTEGER (0..255), + msg1-FDM ENUMERATED {one, two, four, eight}, + msg1-FrequencyStart INTEGER (0..maxNrofPhysicalResourceBlocks-1), + zeroCorrelationZoneConfig INTEGER(0..15), + preambleReceivedTargetPower INTEGER (-202..-60), + preambleTransMax ENUMERATED {n3, n4, n5, n6, n7, n8, n10, n20, n50, n100, n200}, + powerRampingStep ENUMERATED {dB0, dB2, dB4, dB6}, + ra-ResponseWindow ENUMERATED {sl1, sl2, sl4, sl8, sl10, sl20, sl40, sl80}, + ..., + [[ + prach-ConfigurationPeriodScaling-IAB-r16 ENUMERATED {scf1,scf2,scf4,scf8,scf16,scf32,scf64} OPTIONAL, -- Need R + prach-ConfigurationFrameOffset-IAB-r16 INTEGER (0..63) OPTIONAL, -- Need R + prach-ConfigurationSOffset-IAB-r16 INTEGER (0..39) OPTIONAL, -- Need R + ra-ResponseWindow-v1610 ENUMERATED { sl60, sl160} OPTIONAL, -- Need R + prach-ConfigurationIndex-v1610 INTEGER (256..262) OPTIONAL -- Need R + ]] +} + +-- TAG-RACH-CONFIGGENERIC-STOP +-- TAG-RACH-CONFIGGENERICTWOSTEPRA-START + +RACH-ConfigGenericTwoStepRA-r16 ::= SEQUENCE { + msgA-PRACH-ConfigurationIndex-r16 INTEGER (0..262) OPTIONAL, -- Cond 2StepOnly + msgA-RO-FDM-r16 ENUMERATED {one, two, four, eight} OPTIONAL, -- Cond 2StepOnly + msgA-RO-FrequencyStart-r16 INTEGER (0..maxNrofPhysicalResourceBlocks-1) OPTIONAL, -- Cond 2StepOnly + msgA-ZeroCorrelationZoneConfig-r16 INTEGER (0..15) OPTIONAL, -- Cond 2StepOnly + msgA-PreamblePowerRampingStep-r16 ENUMERATED {dB0, dB2, dB4, dB6} OPTIONAL, -- Cond 2StepOnlyNoCFRA + msgA-PreambleReceivedTargetPower-r16 INTEGER (-202..-60) OPTIONAL, -- Cond 2StepOnlyNoCFRA + msgB-ResponseWindow-r16 ENUMERATED {sl1, sl2, sl4, sl8, sl10, sl20, sl40, sl80, sl160, sl320} + OPTIONAL, -- Cond NoCFRA + preambleTransMax-r16 ENUMERATED {n3, n4, n5, n6, n7, n8, n10, n20, n50, n100, n200} OPTIONAL, -- Cond 2StepOnlyNoCFRA + ... +} + +-- TAG-RACH-CONFIGGENERICTWOSTEPRA-STOP +-- TAG-RA-PRIORITIZATION-START + +RA-Prioritization ::= SEQUENCE { + powerRampingStepHighPriority ENUMERATED {dB0, dB2, dB4, dB6}, + scalingFactorBI ENUMERATED {zero, dot25, dot5, dot75} OPTIONAL, -- Need R + ... +} + +-- TAG-RA-PRIORITIZATION-STOP +-- TAG-RADIOBEARERCONFIG-START + +RadioBearerConfig ::= SEQUENCE { + srb-ToAddModList SRB-ToAddModList OPTIONAL, -- Cond HO-Conn + srb3-ToRelease ENUMERATED{true} OPTIONAL, -- Need N + drb-ToAddModList DRB-ToAddModList OPTIONAL, -- Cond HO-toNR + drb-ToReleaseList DRB-ToReleaseList OPTIONAL, -- Need N + securityConfig SecurityConfig OPTIONAL, -- Need M + ... +} + +SRB-ToAddModList ::= SEQUENCE (SIZE (1..2)) OF SRB-ToAddMod +SRB-ToAddMod ::= SEQUENCE { + srb-Identity SRB-Identity, + reestablishPDCP ENUMERATED{true} OPTIONAL, -- Need N + discardOnPDCP ENUMERATED{true} OPTIONAL, -- Need N + pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP + ... +} + +DRB-ToAddModList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-ToAddMod + +DRB-ToAddMod ::= SEQUENCE { + cnAssociation CHOICE { + eps-BearerIdentity INTEGER (0..15), + sdap-Config SDAP-Config + } OPTIONAL, -- Cond DRBSetup + drb-Identity DRB-Identity, + reestablishPDCP ENUMERATED{true} OPTIONAL, -- Need N + recoverPDCP ENUMERATED{true} OPTIONAL, -- Need N + pdcp-Config PDCP-Config OPTIONAL, -- Cond PDCP + ..., + [[ + daps-Config-r16 ENUMERATED{true} OPTIONAL -- Cond DAPS + ]] +} +DRB-ToReleaseList ::= SEQUENCE (SIZE (1..maxDRB)) OF DRB-Identity + +SecurityConfig ::= SEQUENCE { + securityAlgorithmConfig SecurityAlgorithmConfig OPTIONAL, -- Cond RBTermChange1 + keyToUse ENUMERATED{master, secondary} OPTIONAL, -- Cond RBTermChange + ... +} + +-- TAG-RADIOBEARERCONFIG-STOP +-- TAG-RADIOLINKMONITORINGCONFIG-START + +RadioLinkMonitoringConfig ::= SEQUENCE { + failureDetectionResourcesToAddModList SEQUENCE (SIZE(1..maxNrofFailureDetectionResources)) OF RadioLinkMonitoringRS + OPTIONAL, -- Need N + failureDetectionResourcesToReleaseList SEQUENCE (SIZE(1..maxNrofFailureDetectionResources)) OF RadioLinkMonitoringRS-Id + OPTIONAL, -- Need N + beamFailureInstanceMaxCount ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10} OPTIONAL, -- Need R + beamFailureDetectionTimer ENUMERATED {pbfd1, pbfd2, pbfd3, pbfd4, pbfd5, pbfd6, pbfd8, pbfd10} OPTIONAL, -- Need R + ... +} + +RadioLinkMonitoringRS ::= SEQUENCE { + radioLinkMonitoringRS-Id RadioLinkMonitoringRS-Id, + purpose ENUMERATED {beamFailure, rlf, both}, + detectionResource CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId + }, + ... +} + +-- TAG-RADIOLINKMONITORINGCONFIG-STOP +-- TAG-RADIOLINKMONITORINGRS-ID-START + +RadioLinkMonitoringRS-Id ::= INTEGER (0..maxNrofFailureDetectionResources-1) + +-- TAG-RADIOLINKMONITORINGRS-ID-STOP +-- TAG-RAN-AREACODE-START + +RAN-AreaCode ::= INTEGER (0..255) + +-- TAG-RAN-AREACODE-STOP +-- TAG-RATEMATCHPATTERN-START + +RateMatchPattern ::= SEQUENCE { + rateMatchPatternId RateMatchPatternId, + + patternType CHOICE { + bitmaps SEQUENCE { + resourceBlocks BIT STRING (SIZE (275)), + symbolsInResourceBlock CHOICE { + oneSlot BIT STRING (SIZE (14)), + twoSlots BIT STRING (SIZE (28)) + }, + periodicityAndPattern CHOICE { + n2 BIT STRING (SIZE (2)), + n4 BIT STRING (SIZE (4)), + n5 BIT STRING (SIZE (5)), + n8 BIT STRING (SIZE (8)), + n10 BIT STRING (SIZE (10)), + n20 BIT STRING (SIZE (20)), + n40 BIT STRING (SIZE (40)) + } OPTIONAL, -- Need S + ... + }, + controlResourceSet ControlResourceSetId + }, + subcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond CellLevel + dummy ENUMERATED { dynamic, semiStatic }, + ..., + [[ + controlResourceSet-r16 ControlResourceSetId-r16 OPTIONAL -- Need R + ]] + +} + +-- TAG-RATEMATCHPATTERN-STOP +-- TAG-RATEMATCHPATTERNID-START + +RateMatchPatternId ::= INTEGER (0..maxNrofRateMatchPatterns-1) + +-- TAG-RATEMATCHPATTERNID-STOP +-- TAG-RATEMATCHPATTERNLTE-CRS-START + +RateMatchPatternLTE-CRS ::= SEQUENCE { + carrierFreqDL INTEGER (0..16383), + carrierBandwidthDL ENUMERATED {n6, n15, n25, n50, n75, n100, spare2, spare1}, + mbsfn-SubframeConfigList EUTRA-MBSFN-SubframeConfigList OPTIONAL, -- Need M + nrofCRS-Ports ENUMERATED {n1, n2, n4}, + v-Shift ENUMERATED {n0, n1, n2, n3, n4, n5} +} + +LTE-CRS-PatternList-r16 ::= SEQUENCE (SIZE (1..maxLTE-CRS-Patterns-r16)) OF RateMatchPatternLTE-CRS + +-- TAG-RATEMATCHPATTERNLTE-CRS-STOP +-- TAG-REFERENCETIMEINFO-START + +ReferenceTimeInfo-r16 ::= SEQUENCE { + time-r16 ReferenceTime-r16, + uncertainty-r16 INTEGER (0..32767) OPTIONAL, -- Need S + timeInfoType-r16 ENUMERATED {localClock} OPTIONAL, -- Need S + referenceSFN-r16 INTEGER (0..1023) OPTIONAL -- Cond RefTime +} + +ReferenceTime-r16 ::= SEQUENCE { + refDays-r16 INTEGER (0..72999), + refSeconds-r16 INTEGER (0..86399), + refMilliSeconds-r16 INTEGER (0..999), + refTenNanoSeconds-r16 INTEGER (0..99999) +} + +-- TAG-REFERENCETIMEINFO-STOP +-- TAG-REJECTWAITTIME-START + +RejectWaitTime ::= INTEGER (1..16) + +-- TAG-REJECTWAITTIME-STOP +-- TAG-REPETITIONSCHEMECONFIG-START + +RepetitionSchemeConfig-r16 ::= CHOICE { + fdm-TDM-r16 SetupRelease { FDM-TDM-r16 }, + slotBased-r16 SetupRelease { SlotBased-r16 } +} + +RepetitionSchemeConfig-v1630 ::= SEQUENCE { + slotBased-v1630 SetupRelease { SlotBased-v1630 } +} + +FDM-TDM-r16 ::= SEQUENCE { + repetitionScheme-r16 ENUMERATED {fdmSchemeA, fdmSchemeB,tdmSchemeA }, + startingSymbolOffsetK-r16 INTEGER (0..7) OPTIONAL -- Need R +} + +SlotBased-r16 ::= SEQUENCE { + tciMapping-r16 ENUMERATED {cyclicMapping, sequentialMapping}, + sequenceOffsetForRV-r16 INTEGER (1..3) +} + +SlotBased-v1630 ::= SEQUENCE { + tciMapping-r16 ENUMERATED {cyclicMapping, sequentialMapping}, + sequenceOffsetForRV-r16 INTEGER (0) +} + +-- TAG-REPETITIONSCHEMECONFIG-STOP +-- TAG-REPORTCONFIGID-START + +ReportConfigId ::= INTEGER (1..maxReportConfigId) + +-- TAG-REPORTCONFIGID-STOP +-- TAG-REPORTCONFIGINTERRAT-START + +ReportConfigInterRAT ::= SEQUENCE { + reportType CHOICE { + periodical PeriodicalReportConfigInterRAT, + eventTriggered EventTriggerConfigInterRAT, + reportCGI ReportCGI-EUTRA, + ..., + reportSFTD ReportSFTD-EUTRA + } +} + +ReportCGI-EUTRA ::= SEQUENCE { + cellForWhichToReportCGI EUTRA-PhysCellId, + ..., + [[ + useAutonomousGaps-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] +} + +ReportSFTD-EUTRA ::= SEQUENCE { + reportSFTD-Meas BOOLEAN, + reportRSRP BOOLEAN, + ... +} + +EventTriggerConfigInterRAT ::= SEQUENCE { + eventId CHOICE { + eventB1 SEQUENCE { + b1-ThresholdEUTRA MeasTriggerQuantityEUTRA, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + ... + }, + eventB2 SEQUENCE { + b2-Threshold1 MeasTriggerQuantity, + b2-Threshold2EUTRA MeasTriggerQuantityEUTRA, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + ... + }, + ..., + [[ + eventB1-UTRA-FDD-r16 SEQUENCE { + b1-ThresholdUTRA-FDD-r16 MeasTriggerQuantityUTRA-FDD-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger, + ... + }, + eventB2-UTRA-FDD-r16 SEQUENCE { + b2-Threshold1-r16 MeasTriggerQuantity, + b2-Threshold2UTRA-FDD-r16 MeasTriggerQuantityUTRA-FDD-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger, + ... + } + ]] + }, + rsType NR-RS-Type, + + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + ..., + [[ + reportQuantityUTRA-FDD-r16 MeasReportQuantityUTRA-FDD-r16 OPTIONAL -- Need R + ]] + + +} + +PeriodicalReportConfigInterRAT ::= SEQUENCE { + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + ..., + [[ + reportQuantityUTRA-FDD-r16 MeasReportQuantityUTRA-FDD-r16 OPTIONAL -- Need R + ]] +} + +MeasTriggerQuantityUTRA-FDD-r16 ::= CHOICE{ + utra-FDD-RSCP-r16 INTEGER (-5..91), + utra-FDD-EcN0-r16 INTEGER (0..49) +} + +MeasReportQuantityUTRA-FDD-r16 ::= SEQUENCE { + cpich-RSCP BOOLEAN, + cpich-EcN0 BOOLEAN +} + +-- TAG-REPORTCONFIGINTERRAT-STOP +-- TAG-REPORTCONFIGNR-START + +ReportConfigNR ::= SEQUENCE { + reportType CHOICE { + periodical PeriodicalReportConfig, + eventTriggered EventTriggerConfig, + ..., + reportCGI ReportCGI, + reportSFTD ReportSFTD-NR, + condTriggerConfig-r16 CondTriggerConfig-r16, + cli-Periodical-r16 CLI-PeriodicalReportConfig-r16, + cli-EventTriggered-r16 CLI-EventTriggerConfig-r16 + } +} + +ReportCGI ::= SEQUENCE { + cellForWhichToReportCGI PhysCellId, + ..., + [[ + useAutonomousGaps-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] + +} + +ReportSFTD-NR ::= SEQUENCE { + reportSFTD-Meas BOOLEAN, + reportRSRP BOOLEAN, + ..., + [[ + reportSFTD-NeighMeas ENUMERATED {true} OPTIONAL, -- Need R + drx-SFTD-NeighMeas ENUMERATED {true} OPTIONAL, -- Need R + cellsForWhichToReportSFTD SEQUENCE (SIZE (1..maxCellSFTD)) OF PhysCellId OPTIONAL -- Need R + ]] +} + +CondTriggerConfig-r16 ::= SEQUENCE { + condEventId CHOICE { + condEventA3 SEQUENCE { + a3-Offset MeasTriggerQuantityOffset, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + condEventA5 SEQUENCE { + a5-Threshold1 MeasTriggerQuantity, + a5-Threshold2 MeasTriggerQuantity, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + ... + }, + rsType-r16 NR-RS-Type, + ... +} + +EventTriggerConfig::= SEQUENCE { + eventId CHOICE { + eventA1 SEQUENCE { + a1-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + eventA2 SEQUENCE { + a2-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger + }, + eventA3 SEQUENCE { + a3-Offset MeasTriggerQuantityOffset, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA4 SEQUENCE { + a4-Threshold MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA5 SEQUENCE { + a5-Threshold1 MeasTriggerQuantity, + a5-Threshold2 MeasTriggerQuantity, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + eventA6 SEQUENCE { + a6-Offset MeasTriggerQuantityOffset, + reportOnLeave BOOLEAN, + hysteresis Hysteresis, + timeToTrigger TimeToTrigger, + useWhiteCellList BOOLEAN + }, + ... + }, + rsType NR-RS-Type, + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantityCell MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + reportQuantityRS-Indexes MeasReportQuantity OPTIONAL, -- Need R + maxNrofRS-IndexesToReport INTEGER (1..maxNrofIndexesToReport) OPTIONAL, -- Need R + includeBeamMeasurements BOOLEAN, + reportAddNeighMeas ENUMERATED {setup} OPTIONAL, -- Need R + ..., + [[ + measRSSI-ReportConfig-r16 MeasRSSI-ReportConfig-r16 OPTIONAL, -- Need R + useT312-r16 BOOLEAN OPTIONAL, -- Need M + includeCommonLocationInfo-r16 ENUMERATED {true} OPTIONAL, -- Need R + includeBT-Meas-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + includeWLAN-Meas-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + includeSensor-Meas-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL -- Need M + ]] +} + +PeriodicalReportConfig ::= SEQUENCE { + rsType NR-RS-Type, + reportInterval ReportInterval, + reportAmount ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantityCell MeasReportQuantity, + maxReportCells INTEGER (1..maxCellReport), + reportQuantityRS-Indexes MeasReportQuantity OPTIONAL, -- Need R + maxNrofRS-IndexesToReport INTEGER (1..maxNrofIndexesToReport) OPTIONAL, -- Need R + includeBeamMeasurements BOOLEAN, + useWhiteCellList BOOLEAN, + ..., + [[ + measRSSI-ReportConfig-r16 MeasRSSI-ReportConfig-r16 OPTIONAL, -- Need R + includeCommonLocationInfo-r16 ENUMERATED {true} OPTIONAL, -- Need R + includeBT-Meas-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + includeWLAN-Meas-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + includeSensor-Meas-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, -- Need M + ul-DelayValueConfig-r16 SetupRelease { UL-DelayValueConfig-r16 } OPTIONAL, -- Need M + reportAddNeighMeas-r16 ENUMERATED {setup} OPTIONAL -- Need R + ]] +} + +NR-RS-Type ::= ENUMERATED {ssb, csi-rs} + +MeasTriggerQuantity ::= CHOICE { + rsrp RSRP-Range, + rsrq RSRQ-Range, + sinr SINR-Range +} + +MeasTriggerQuantityOffset ::= CHOICE { + rsrp INTEGER (-30..30), + rsrq INTEGER (-30..30), + sinr INTEGER (-30..30) +} + + +MeasReportQuantity ::= SEQUENCE { + rsrp BOOLEAN, + rsrq BOOLEAN, + sinr BOOLEAN +} + +MeasRSSI-ReportConfig-r16 ::= SEQUENCE { + channelOccupancyThreshold-r16 RSSI-Range-r16 OPTIONAL -- Need R +} + +CLI-EventTriggerConfig-r16 ::= SEQUENCE { + eventId-r16 CHOICE { + eventI1-r16 SEQUENCE { + i1-Threshold-r16 MeasTriggerQuantityCLI-r16, + reportOnLeave-r16 BOOLEAN, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + ... + }, + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + maxReportCLI-r16 INTEGER (1..maxCLI-Report-r16), + ... +} + +CLI-PeriodicalReportConfig-r16 ::= SEQUENCE { + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantityCLI-r16 MeasReportQuantityCLI-r16, + maxReportCLI-r16 INTEGER (1..maxCLI-Report-r16), + ... +} + +MeasTriggerQuantityCLI-r16 ::= CHOICE { + srs-RSRP-r16 SRS-RSRP-Range-r16, + cli-RSSI-r16 CLI-RSSI-Range-r16 +} + +MeasReportQuantityCLI-r16 ::= ENUMERATED {srs-rsrp, cli-rssi} + +-- TAG-REPORTCONFIGNR-STOP +-- TAG-REPORTCONFIGNR-SL-START + +ReportConfigNR-SL-r16 ::= SEQUENCE { + reportType-r16 CHOICE { + periodical-r16 PeriodicalReportConfigNR-SL-r16, + eventTriggered-r16 EventTriggerConfigNR-SL-r16 + } +} + +EventTriggerConfigNR-SL-r16::= SEQUENCE { + eventId-r16 CHOICE { + eventC1 SEQUENCE { + c1-Threshold-r16 SL-CBR-r16, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + eventC2-r16 SEQUENCE { + c2-Threshold-r16 SL-CBR-r16, + hysteresis-r16 Hysteresis, + timeToTrigger-r16 TimeToTrigger + }, + ... + }, + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity-r16 MeasReportQuantity-r16, + ... +} + +PeriodicalReportConfigNR-SL-r16 ::= SEQUENCE { + reportInterval-r16 ReportInterval, + reportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + reportQuantity-r16 MeasReportQuantity-r16, + ... +} + +MeasReportQuantity-r16 ::= SEQUENCE { + cbr-r16 BOOLEAN, + ... +} + +-- TAG-REPORTCONFIGNR-SL-STOP +-- TAG-REPORTCONFIGTOADDMODLIST-START + +ReportConfigToAddModList ::= SEQUENCE (SIZE (1..maxReportConfigId)) OF ReportConfigToAddMod + +ReportConfigToAddMod ::= SEQUENCE { + reportConfigId ReportConfigId, + reportConfig CHOICE { + reportConfigNR ReportConfigNR, + ..., + reportConfigInterRAT ReportConfigInterRAT, + reportConfigNR-SL-r16 ReportConfigNR-SL-r16 + } +} + +-- TAG-REPORTCONFIGTOADDMODLIST-STOP +-- TAG-REPORTINTERVAL-START + +ReportInterval ::= ENUMERATED {ms120, ms240, ms480, ms640, ms1024, ms2048, ms5120, ms10240, ms20480, ms40960, + min1,min6, min12, min30 } + +-- TAG-REPORTINTERVAL-STOP +-- TAG-RESELECTIONTHRESHOLD-START + +ReselectionThreshold ::= INTEGER (0..31) + +-- TAG-RESELECTIONTHRESHOLD-STOP +-- TAG-RESELECTIONTHRESHOLDQ-START + +ReselectionThresholdQ ::= INTEGER (0..31) + +-- TAG-RESELECTIONTHRESHOLDQ-STOP +-- TAG-RESUMECAUSE-START + +ResumeCause ::= ENUMERATED {emergency, highPriorityAccess, mt-Access, mo-Signalling, + mo-Data, mo-VoiceCall, mo-VideoCall, mo-SMS, rna-Update, mps-PriorityAccess, + mcs-PriorityAccess, spare1, spare2, spare3, spare4, spare5 } + +-- TAG-RESUMECAUSE-STOP +-- TAG-RLC-BEARERCONFIG-START + +RLC-BearerConfig ::= SEQUENCE { + logicalChannelIdentity LogicalChannelIdentity, + servedRadioBearer CHOICE { + srb-Identity SRB-Identity, + drb-Identity DRB-Identity + } OPTIONAL, -- Cond LCH-SetupOnly + reestablishRLC ENUMERATED {true} OPTIONAL, -- Need N + rlc-Config RLC-Config OPTIONAL, -- Cond LCH-Setup + mac-LogicalChannelConfig LogicalChannelConfig OPTIONAL, -- Cond LCH-Setup + ..., + [[ + rlc-Config-v1610 RLC-Config-v1610 OPTIONAL -- Need R + ]] +} + +-- TAG-RLC-BEARERCONFIG-STOP +-- TAG-RLC-CONFIG-START + +RLC-Config ::= CHOICE { + am SEQUENCE { + ul-AM-RLC UL-AM-RLC, + dl-AM-RLC DL-AM-RLC + }, + um-Bi-Directional SEQUENCE { + ul-UM-RLC UL-UM-RLC, + dl-UM-RLC DL-UM-RLC + }, + um-Uni-Directional-UL SEQUENCE { + ul-UM-RLC UL-UM-RLC + }, + um-Uni-Directional-DL SEQUENCE { + dl-UM-RLC DL-UM-RLC + }, + ... +} + +UL-AM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthAM OPTIONAL, -- Cond Reestab + t-PollRetransmit T-PollRetransmit, + pollPDU PollPDU, + pollByte PollByte, + maxRetxThreshold ENUMERATED { t1, t2, t3, t4, t6, t8, t16, t32 } +} + +DL-AM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthAM OPTIONAL, -- Cond Reestab + t-Reassembly T-Reassembly, + t-StatusProhibit T-StatusProhibit +} + +UL-UM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthUM OPTIONAL -- Cond Reestab +} + +DL-UM-RLC ::= SEQUENCE { + sn-FieldLength SN-FieldLengthUM OPTIONAL, -- Cond Reestab + t-Reassembly T-Reassembly +} + +T-PollRetransmit ::= ENUMERATED { + ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms105, + ms110, ms115, ms120, ms125, ms130, ms135, + ms140, ms145, ms150, ms155, ms160, ms165, + ms170, ms175, ms180, ms185, ms190, ms195, + ms200, ms205, ms210, ms215, ms220, ms225, + ms230, ms235, ms240, ms245, ms250, ms300, + ms350, ms400, ms450, ms500, ms800, ms1000, + ms2000, ms4000, ms1-v1610, ms2-v1610, ms3-v1610, + ms4-v1610, spare1} + + +PollPDU ::= ENUMERATED { + p4, p8, p16, p32, p64, p128, p256, p512, p1024, p2048, p4096, p6144, p8192, p12288, p16384,p20480, + p24576, p28672, p32768, p40960, p49152, p57344, p65536, infinity, spare8, spare7, spare6, spare5, spare4, + spare3, spare2, spare1} + +PollByte ::= ENUMERATED { + kB1, kB2, kB5, kB8, kB10, kB15, kB25, kB50, kB75, + kB100, kB125, kB250, kB375, kB500, kB750, kB1000, + kB1250, kB1500, kB2000, kB3000, kB4000, kB4500, + kB5000, kB5500, kB6000, kB6500, kB7000, kB7500, + mB8, mB9, mB10, mB11, mB12, mB13, mB14, mB15, + mB16, mB17, mB18, mB20, mB25, mB30, mB40, infinity, + spare20, spare19, spare18, spare17, spare16, + spare15, spare14, spare13, spare12, spare11, + spare10, spare9, spare8, spare7, spare6, spare5, + spare4, spare3, spare2, spare1} + +T-Reassembly ::= ENUMERATED { + ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms110, + ms120, ms130, ms140, ms150, ms160, ms170, + ms180, ms190, ms200, spare1} + +T-StatusProhibit ::= ENUMERATED { + ms0, ms5, ms10, ms15, ms20, ms25, ms30, ms35, + ms40, ms45, ms50, ms55, ms60, ms65, ms70, + ms75, ms80, ms85, ms90, ms95, ms100, ms105, + ms110, ms115, ms120, ms125, ms130, ms135, + ms140, ms145, ms150, ms155, ms160, ms165, + ms170, ms175, ms180, ms185, ms190, ms195, + ms200, ms205, ms210, ms215, ms220, ms225, + ms230, ms235, ms240, ms245, ms250, ms300, + ms350, ms400, ms450, ms500, ms800, ms1000, + ms1200, ms1600, ms2000, ms2400, spare2, spare1} + +SN-FieldLengthUM ::= ENUMERATED {size6, size12} +SN-FieldLengthAM ::= ENUMERATED {size12, size18} + +RLC-Config-v1610 ::= SEQUENCE { + dl-AM-RLC-v1610 DL-AM-RLC-v1610 +} + +DL-AM-RLC-v1610 ::= SEQUENCE { + t-StatusProhibit-v1610 T-StatusProhibit-v1610 OPTIONAL, -- Need N + ... +} + +T-StatusProhibit-v1610 ::= ENUMERATED { ms1, ms2, ms3, ms4, spare4, spare3, spare2, spare1} + +-- TAG-RLC-CONFIG-STOP +-- TAG-RLF-TIMERSANDCONSTANTS-START + +RLF-TimersAndConstants ::= SEQUENCE { + t310 ENUMERATED {ms0, ms50, ms100, ms200, ms500, ms1000, ms2000, ms4000, ms6000}, + n310 ENUMERATED {n1, n2, n3, n4, n6, n8, n10, n20}, + n311 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10}, + ..., + [[ + t311 ENUMERATED {ms1000, ms3000, ms5000, ms10000, ms15000, ms20000, ms30000} + ]] +} + +-- TAG-RLF-TIMERSANDCONSTANTS-STOP +-- TAG-RNTI-VALUE-START + +RNTI-Value ::= INTEGER (0..65535) + +-- TAG-RNTI-VALUE-STOP +-- TAG-RSRP-RANGE-START + +RSRP-Range ::= INTEGER(0..127) + +-- TAG-RSRP-RANGE-STOP +-- TAG-RSRQ-RANGE-START + +RSRQ-Range ::= INTEGER(0..127) + +-- TAG-RSRQ-RANGE-STOP +-- TAG-RSSI-RANGE-START + +RSSI-Range-r16 ::= INTEGER(0..76) + +-- TAG-RSSI-RANGE-STOP +-- TAG-SCELLINDEX-START + +SCellIndex ::= INTEGER (1..31) + +-- TAG-SCELLINDEX-STOP +-- TAG-SCHEDULINGREQUESTCONFIG-START + +SchedulingRequestConfig ::= SEQUENCE { + schedulingRequestToAddModList SEQUENCE (SIZE (1..maxNrofSR-ConfigPerCellGroup)) OF SchedulingRequestToAddMod + OPTIONAL, -- Need N + schedulingRequestToReleaseList SEQUENCE (SIZE (1..maxNrofSR-ConfigPerCellGroup)) OF SchedulingRequestId + OPTIONAL -- Need N +} + +SchedulingRequestToAddMod ::= SEQUENCE { + schedulingRequestId SchedulingRequestId, + sr-ProhibitTimer ENUMERATED {ms1, ms2, ms4, ms8, ms16, ms32, ms64, ms128} OPTIONAL, -- Need S + sr-TransMax ENUMERATED { n4, n8, n16, n32, n64, spare3, spare2, spare1} +} + + + +-- TAG-SCHEDULINGREQUESTCONFIG-STOP +-- TAG-SCHEDULINGREQUESTID-START + +SchedulingRequestId ::= INTEGER (0..7) + +-- TAG-SCHEDULINGREQUESTID-STOP +-- TAG-SCHEDULINGREQUESTRESOURCECONFIG-START + +SchedulingRequestResourceConfig ::= SEQUENCE { + schedulingRequestResourceId SchedulingRequestResourceId, + schedulingRequestID SchedulingRequestId, + periodicityAndOffset CHOICE { + sym2 NULL, + sym6or7 NULL, + sl1 NULL, -- Recurs in every slot + sl2 INTEGER (0..1), + sl4 INTEGER (0..3), + sl5 INTEGER (0..4), + sl8 INTEGER (0..7), + sl10 INTEGER (0..9), + sl16 INTEGER (0..15), + sl20 INTEGER (0..19), + sl40 INTEGER (0..39), + sl80 INTEGER (0..79), + sl160 INTEGER (0..159), + sl320 INTEGER (0..319), + sl640 INTEGER (0..639) + } OPTIONAL, -- Need M + resource PUCCH-ResourceId OPTIONAL -- Need M +} + +SchedulingRequestResourceConfigExt-v1610 ::= SEQUENCE { + phy-PriorityIndex-r16 ENUMERATED {p0, p1} OPTIONAL, -- Need M + ... +} + +-- TAG-SCHEDULINGREQUESTRESOURCECONFIG-STOP +-- TAG-SCHEDULINGREQUESTRESOURCEID-START + +SchedulingRequestResourceId ::= INTEGER (1..maxNrofSR-Resources) + +-- TAG-SCHEDULINGREQUESTRESOURCEID-STOP +-- TAG-SCRAMBLINGID-START + +ScramblingId ::= INTEGER(0..1023) + +-- TAG-SCRAMBLINGID-STOP +-- TAG-SCS-SPECIFICCARRIER-START + +SCS-SpecificCarrier ::= SEQUENCE { + offsetToCarrier INTEGER (0..2199), + subcarrierSpacing SubcarrierSpacing, + carrierBandwidth INTEGER (1..maxNrofPhysicalResourceBlocks), + ..., + [[ + txDirectCurrentLocation INTEGER (0..4095) OPTIONAL -- Need S + ]] +} + +-- TAG-SCS-SPECIFICCARRIER-STOP +-- TAG-SDAP-CONFIG-START + +SDAP-Config ::= SEQUENCE { + pdu-Session PDU-SessionID, + sdap-HeaderDL ENUMERATED {present, absent}, + sdap-HeaderUL ENUMERATED {present, absent}, + defaultDRB BOOLEAN, + mappedQoS-FlowsToAdd SEQUENCE (SIZE (1..maxNrofQFIs)) OF QFI OPTIONAL, -- Need N + mappedQoS-FlowsToRelease SEQUENCE (SIZE (1..maxNrofQFIs)) OF QFI OPTIONAL, -- Need N + ... +} + +QFI ::= INTEGER (0..maxQFI) + +PDU-SessionID ::= INTEGER (0..255) + +-- TAG-SDAP-CONFIG-STOP +-- TAG-SEARCHSPACE-START + +SearchSpace ::= SEQUENCE { + searchSpaceId SearchSpaceId, + controlResourceSetId ControlResourceSetId OPTIONAL, -- Cond SetupOnly + monitoringSlotPeriodicityAndOffset CHOICE { + sl1 NULL, + sl2 INTEGER (0..1), + sl4 INTEGER (0..3), + sl5 INTEGER (0..4), + sl8 INTEGER (0..7), + sl10 INTEGER (0..9), + sl16 INTEGER (0..15), + sl20 INTEGER (0..19), + sl40 INTEGER (0..39), + sl80 INTEGER (0..79), + sl160 INTEGER (0..159), + sl320 INTEGER (0..319), + sl640 INTEGER (0..639), + sl1280 INTEGER (0..1279), + sl2560 INTEGER (0..2559) + } OPTIONAL, -- Cond Setup + duration INTEGER (2..2559) OPTIONAL, -- Need R + monitoringSymbolsWithinSlot BIT STRING (SIZE (14)) OPTIONAL, -- Cond Setup + nrofCandidates SEQUENCE { + aggregationLevel1 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel2 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel4 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel8 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8}, + aggregationLevel16 ENUMERATED {n0, n1, n2, n3, n4, n5, n6, n8} + } OPTIONAL, -- Cond Setup + searchSpaceType CHOICE { + common SEQUENCE { + dci-Format0-0-AndFormat1-0 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-0 SEQUENCE { + nrofCandidates-SFI SEQUENCE { + aggregationLevel1 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-1 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-2 SEQUENCE { + ... + } OPTIONAL, -- Need R + dci-Format2-3 SEQUENCE { + dummy1 ENUMERATED {sl1, sl2, sl4, sl5, sl8, sl10, sl16, sl20} OPTIONAL, -- Cond Setup + dummy2 ENUMERATED {n1, n2}, + ... + } OPTIONAL -- Need R + }, + ue-Specific SEQUENCE { + dci-Formats ENUMERATED {formats0-0-And-1-0, formats0-1-And-1-1}, + ..., + [[ + dci-Formats-MT-r16 ENUMERATED {formats2-5} OPTIONAL, -- Need R + dci-FormatsSL-r16 ENUMERATED {formats0-0-And-1-0, formats0-1-And-1-1, formats3-0, formats3-1, + formats3-0-And-3-1} OPTIONAL, -- Need R + dci-FormatsExt-r16 ENUMERATED {formats0-2-And-1-2, formats0-1-And-1-1And-0-2-And-1-2} + OPTIONAL -- Need R + ]] + } + } OPTIONAL -- Cond Setup2 +} + +SearchSpaceExt-r16 ::= SEQUENCE { + controlResourceSetId-r16 ControlResourceSetId-r16 OPTIONAL, -- Cond SetupOnly2 + searchSpaceType-r16 SEQUENCE { + common-r16 SEQUENCE { + dci-Format2-4-r16 SEQUENCE { + nrofCandidates-CI-r16 SEQUENCE { + aggregationLevel1-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-5-r16 SEQUENCE { + nrofCandidates-IAB-r16 SEQUENCE { + aggregationLevel1-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel2-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel4-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel8-r16 ENUMERATED {n1, n2} OPTIONAL, -- Need R + aggregationLevel16-r16 ENUMERATED {n1, n2} OPTIONAL -- Need R + }, + ... + } OPTIONAL, -- Need R + dci-Format2-6-r16 SEQUENCE { + ... + } OPTIONAL, -- Need R + ... + } + } OPTIONAL, -- Cond Setup3 + searchSpaceGroupIdList-r16 SEQUENCE (SIZE (1.. 2)) OF INTEGER (0..1) OPTIONAL, -- Need R + freqMonitorLocations-r16 BIT STRING (SIZE (5)) OPTIONAL -- Need R +} + +-- TAG-SEARCHSPACE-STOP +-- TAG-SEARCHSPACEID-START + +SearchSpaceId ::= INTEGER (0..maxNrofSearchSpaces-1) + +-- TAG-SEARCHSPACEID-STOP +-- TAG-SEARCHSPACEZERO-START + +SearchSpaceZero ::= INTEGER (0..15) + +-- TAG-SEARCHSPACEZERO-STOP +-- TAG-SECURITYALGORITHMCONFIG-START + +SecurityAlgorithmConfig ::= SEQUENCE { + cipheringAlgorithm CipheringAlgorithm, + integrityProtAlgorithm IntegrityProtAlgorithm OPTIONAL, -- Need R + ... +} + +IntegrityProtAlgorithm ::= ENUMERATED { + nia0, nia1, nia2, nia3, spare4, spare3, + spare2, spare1, ...} + +CipheringAlgorithm ::= ENUMERATED { + nea0, nea1, nea2, nea3, spare4, spare3, + spare2, spare1, ...} + +-- TAG-SECURITYALGORITHMCONFIG-STOP +-- TAG-SEMISTATICCHANNELACCESSCONFIG-START + +SemiStaticChannelAccessConfig-r16 ::= SEQUENCE { + period ENUMERATED {ms1, ms2, ms2dot5, ms4, ms5, ms10} +} + +-- TAG-SEMISTATICCHANNELACCESSCONFIG-STOP +-- TAG-SENSORLOCATIONINFO-START + +Sensor-LocationInfo-r16 ::= SEQUENCE { + sensor-MeasurementInformation-r16 OCTET STRING OPTIONAL, + sensor-MotionInformation-r16 OCTET STRING OPTIONAL, + ... +} + +-- TAG-SENSORLOCATIONINFO-STOP +-- TAG-SERVCELLINDEX-START + +ServCellIndex ::= INTEGER (0..maxNrofServingCells-1) + +-- TAG-SERVCELLINDEX-STOP +-- TAG-SERVINGCELLCONFIG-START + +ServingCellConfig ::= SEQUENCE { + tdd-UL-DL-ConfigurationDedicated TDD-UL-DL-ConfigDedicated OPTIONAL, -- Cond TDD + initialDownlinkBWP BWP-DownlinkDedicated OPTIONAL, -- Need M + downlinkBWP-ToReleaseList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Id OPTIONAL, -- Need N + downlinkBWP-ToAddModList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Downlink OPTIONAL, -- Need N + firstActiveDownlinkBWP-Id BWP-Id OPTIONAL, -- Cond SyncAndCellAdd + bwp-InactivityTimer ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, + ms40,ms50, ms60, ms80,ms100, ms200,ms300, ms500, + ms750, ms1280, ms1920, ms2560, spare10, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1 } OPTIONAL, --Need R + defaultDownlinkBWP-Id BWP-Id OPTIONAL, -- Need S + uplinkConfig UplinkConfig OPTIONAL, -- Need M + supplementaryUplink UplinkConfig OPTIONAL, -- Need M + pdcch-ServingCellConfig SetupRelease { PDCCH-ServingCellConfig } OPTIONAL, -- Need M + pdsch-ServingCellConfig SetupRelease { PDSCH-ServingCellConfig } OPTIONAL, -- Need M + csi-MeasConfig SetupRelease { CSI-MeasConfig } OPTIONAL, -- Need M + sCellDeactivationTimer ENUMERATED {ms20, ms40, ms80, ms160, ms200, ms240, + ms320, ms400, ms480, ms520, ms640, ms720, + ms840, ms1280, spare2,spare1} OPTIONAL, -- Cond ServingCellWithoutPUCCH + crossCarrierSchedulingConfig CrossCarrierSchedulingConfig OPTIONAL, -- Need M + tag-Id TAG-Id, + dummy1 ENUMERATED {enabled} OPTIONAL, -- Need R + pathlossReferenceLinking ENUMERATED {spCell, sCell} OPTIONAL, -- Cond SCellOnly + servingCellMO MeasObjectId OPTIONAL, -- Cond MeasObject + ..., + [[ + lte-CRS-ToMatchAround SetupRelease { RateMatchPatternLTE-CRS } OPTIONAL, -- Need M + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + downlinkChannelBW-PerSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier OPTIONAL -- Need S + ]], + [[ + supplementaryUplinkRelease-r16 ENUMERATED {true} OPTIONAL, -- Need N + tdd-UL-DL-ConfigurationDedicated-IAB-MT-r16 TDD-UL-DL-ConfigDedicated-IAB-MT-r16 OPTIONAL, -- Cond TDD_IAB + dormantBWP-Config-r16 SetupRelease { DormantBWP-Config-r16 } OPTIONAL, -- Need M + ca-SlotOffset-r16 CHOICE { + refSCS15kHz INTEGER (-2..2), + refSCS30KHz INTEGER (-5..5), + refSCS60KHz INTEGER (-10..10), + refSCS120KHz INTEGER (-20..20) + } OPTIONAL, -- Cond AsyncCA + dummy2 SetupRelease { DummyJ } OPTIONAL, -- Need M + intraCellGuardBandsDL-List-r16 SEQUENCE (SIZE (1..maxSCSs)) OF IntraCellGuardBandsPerSCS-r16 OPTIONAL, -- Need S + intraCellGuardBandsUL-List-r16 SEQUENCE (SIZE (1..maxSCSs)) OF IntraCellGuardBandsPerSCS-r16 OPTIONAL, -- Need S + csi-RS-ValidationWithDCI-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + lte-CRS-PatternList1-r16 SetupRelease { LTE-CRS-PatternList-r16 } OPTIONAL, -- Need M + lte-CRS-PatternList2-r16 SetupRelease { LTE-CRS-PatternList-r16 } OPTIONAL, -- Need M + crs-RateMatch-PerCORESETPoolIndex-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableTwoDefaultTCI-States-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultTCI-StatePerCoresetPoolIndex-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableBeamSwitchTiming-r16 ENUMERATED {true} OPTIONAL, -- Need R + cbg-TxDiffTBsProcessingType1-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + cbg-TxDiffTBsProcessingType2-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]], + [[ + directionalCollisionHandling-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + channelAccessConfig-r16 SetupRelease { ChannelAccessConfig-r16 } OPTIONAL -- Need M + ]] +} + +UplinkConfig ::= SEQUENCE { + initialUplinkBWP BWP-UplinkDedicated OPTIONAL, -- Need M + uplinkBWP-ToReleaseList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Id OPTIONAL, -- Need N + uplinkBWP-ToAddModList SEQUENCE (SIZE (1..maxNrofBWPs)) OF BWP-Uplink OPTIONAL, -- Need N + firstActiveUplinkBWP-Id BWP-Id OPTIONAL, -- Cond SyncAndCellAdd + pusch-ServingCellConfig SetupRelease { PUSCH-ServingCellConfig } OPTIONAL, -- Need M + carrierSwitching SetupRelease { SRS-CarrierSwitching } OPTIONAL, -- Need M + ..., + [[ + powerBoostPi2BPSK BOOLEAN OPTIONAL, -- Need M + uplinkChannelBW-PerSCS-List SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier OPTIONAL -- Need S + ]], + [[ + enablePL-RS-UpdateForPUSCH-SRS-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForPUSCH0-0-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForPUCCH-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + enableDefaultBeamPL-ForSRS-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + uplinkTxSwitching-r16 SetupRelease { UplinkTxSwitching-r16 } OPTIONAL, -- Need M + mpr-PowerBoost-FR2-r16 ENUMERATED {true} OPTIONAL -- Need R + ]] +} + +DummyJ ::= SEQUENCE { + maxEnergyDetectionThreshold-r16 INTEGER(-85..-52), + energyDetectionThresholdOffset-r16 INTEGER (-20..-13), + ul-toDL-COT-SharingED-Threshold-r16 INTEGER (-85..-52) OPTIONAL, -- Need R + absenceOfAnyOtherTechnology-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +ChannelAccessConfig-r16 ::= SEQUENCE { + energyDetectionConfig-r16 CHOICE { + maxEnergyDetectionThreshold-r16 INTEGER (-85..-52), + energyDetectionThresholdOffset-r16 INTEGER (-13..20) + } OPTIONAL, -- Need R + ul-toDL-COT-SharingED-Threshold-r16 INTEGER (-85..-52) OPTIONAL, -- Need R + absenceOfAnyOtherTechnology-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +IntraCellGuardBandsPerSCS-r16 ::= SEQUENCE { + guardBandSCS-r16 SubcarrierSpacing, + intraCellGuardBands-r16 SEQUENCE (SIZE (1..4)) OF GuardBand-r16 +} + +GuardBand-r16 ::= SEQUENCE { + startCRB-r16 INTEGER (0..274), + nrofCRBs-r16 INTEGER (0..15) +} + +DormancyGroupID-r16 ::= INTEGER (0..4) + +DormantBWP-Config-r16::= SEQUENCE { + dormantBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + withinActiveTimeConfig-r16 SetupRelease { WithinActiveTimeConfig-r16 } OPTIONAL, -- Need M + outsideActiveTimeConfig-r16 SetupRelease { OutsideActiveTimeConfig-r16 } OPTIONAL -- Need M +} + +WithinActiveTimeConfig-r16 ::= SEQUENCE { + firstWithinActiveTimeBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + dormancyGroupWithinActiveTime-r16 DormancyGroupID-r16 OPTIONAL -- Need R +} + +OutsideActiveTimeConfig-r16 ::= SEQUENCE { + firstOutsideActiveTimeBWP-Id-r16 BWP-Id OPTIONAL, -- Need M + dormancyGroupOutsideActiveTime-r16 DormancyGroupID-r16 OPTIONAL -- Need R +} + +UplinkTxSwitching-r16 ::= SEQUENCE { + uplinkTxSwitchingPeriodLocation-r16 BOOLEAN, + uplinkTxSwitchingCarrier-r16 ENUMERATED {carrier1, carrier2} +} + +-- TAG-SERVINGCELLCONFIG-STOP +-- TAG-SERVINGCELLCONFIGCOMMON-START + +ServingCellConfigCommon ::= SEQUENCE { + physCellId PhysCellId OPTIONAL, -- Cond HOAndServCellAdd, + downlinkConfigCommon DownlinkConfigCommon OPTIONAL, -- Cond HOAndServCellAdd + uplinkConfigCommon UplinkConfigCommon OPTIONAL, -- Need M + supplementaryUplinkConfig UplinkConfigCommon OPTIONAL, -- Need S + n-TimingAdvanceOffset ENUMERATED { n0, n25600, n39936 } OPTIONAL, -- Need S + ssb-PositionsInBurst CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)) + } OPTIONAL, -- Cond AbsFreqSSB + ssb-periodicityServingCell ENUMERATED { ms5, ms10, ms20, ms40, ms80, ms160, spare2, spare1 } OPTIONAL, -- Need S + dmrs-TypeA-Position ENUMERATED {pos2, pos3}, + lte-CRS-ToMatchAround SetupRelease { RateMatchPatternLTE-CRS } OPTIONAL, -- Need M + rateMatchPatternToAddModList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPattern OPTIONAL, -- Need N + rateMatchPatternToReleaseList SEQUENCE (SIZE (1..maxNrofRateMatchPatterns)) OF RateMatchPatternId OPTIONAL, -- Need N + ssbSubcarrierSpacing SubcarrierSpacing OPTIONAL, -- Cond HOAndServCellWithSSB + tdd-UL-DL-ConfigurationCommon TDD-UL-DL-ConfigCommon OPTIONAL, -- Cond TDD + ss-PBCH-BlockPower INTEGER (-60..50), + ..., + [[ + channelAccessMode-r16 CHOICE { + dynamic NULL, + semiStatic SemiStaticChannelAccessConfig-r16 + } OPTIONAL, -- Cond SharedSpectrum + discoveryBurstWindowLength-r16 ENUMERATED {ms0dot5, ms1, ms2, ms3, ms4, ms5} OPTIONAL, -- Need R + ssb-PositionQCL-r16 SSB-PositionQCL-Relation-r16 OPTIONAL, -- Cond SharedSpectrum + highSpeedConfig-r16 HighSpeedConfig-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SERVINGCELLCONFIGCOMMON-STOP +-- TAG-SERVINGCELLCONFIGCOMMONSIB-START + +ServingCellConfigCommonSIB ::= SEQUENCE { + downlinkConfigCommon DownlinkConfigCommonSIB, + uplinkConfigCommon UplinkConfigCommonSIB OPTIONAL, -- Need R + supplementaryUplink UplinkConfigCommonSIB OPTIONAL, -- Need R + n-TimingAdvanceOffset ENUMERATED { n0, n25600, n39936 } OPTIONAL, -- Need S + ssb-PositionsInBurst SEQUENCE { + inOneGroup BIT STRING (SIZE (8)), + groupPresence BIT STRING (SIZE (8)) OPTIONAL -- Cond FR2-Only + }, + ssb-PeriodicityServingCell ENUMERATED {ms5, ms10, ms20, ms40, ms80, ms160}, + tdd-UL-DL-ConfigurationCommon TDD-UL-DL-ConfigCommon OPTIONAL, -- Cond TDD + ss-PBCH-BlockPower INTEGER (-60..50), + ..., + [[ + channelAccessMode-r16 CHOICE { + dynamic NULL, + semiStatic SemiStaticChannelAccessConfig-r16 + } OPTIONAL, -- Cond SharedSpectrum + discoveryBurstWindowLength-r16 ENUMERATED {ms0dot5, ms1, ms2, ms3, ms4, ms5} OPTIONAL, -- Need R + highSpeedConfig-r16 HighSpeedConfig-r16 OPTIONAL -- Need R + ]] +} + +-- TAG-SERVINGCELLCONFIGCOMMONSIB-STOP +-- TAG-SHORTI-RNTI-VALUE-START + +ShortI-RNTI-Value ::= BIT STRING (SIZE(24)) + +-- TAG-SHORTI-RNTI-VALUE-STOP +-- TAG-SHORTMAC-I-START + +ShortMAC-I ::= BIT STRING (SIZE (16)) + +-- TAG-SHORTMAC-I-STOP +-- TAG-SINR-RANGE-START + +SINR-Range ::= INTEGER(0..127) + +-- TAG-SINR-RANGE-STOP +-- TAG-SI-REQUESTCONFIG-START + +SI-RequestConfig::= SEQUENCE { + rach-OccasionsSI SEQUENCE { + rach-ConfigSI RACH-ConfigGeneric, + ssb-perRACH-Occasion ENUMERATED {oneEighth, oneFourth, oneHalf, one, two, four, eight, sixteen} + } OPTIONAL, -- Need R + si-RequestPeriod ENUMERATED {one, two, four, six, eight, ten, twelve, sixteen} OPTIONAL, -- Need R + si-RequestResources SEQUENCE (SIZE (1..maxSI-Message)) OF SI-RequestResources +} + +SI-RequestResources ::= SEQUENCE { + ra-PreambleStartIndex INTEGER (0..63), + ra-AssociationPeriodIndex INTEGER (0..15) OPTIONAL, -- Need R + ra-ssb-OccasionMaskIndex INTEGER (0..15) OPTIONAL -- Need R +} + +-- TAG-SI-SCHEDULINGINFO-START + +SI-SchedulingInfo ::= SEQUENCE { + schedulingInfoList SEQUENCE (SIZE (1..maxSI-Message)) OF SchedulingInfo, + si-WindowLength ENUMERATED {s5, s10, s20, s40, s80, s160, s320, s640, s1280}, + si-RequestConfig SI-RequestConfig OPTIONAL, -- Cond MSG-1 + si-RequestConfigSUL SI-RequestConfig OPTIONAL, -- Cond SUL-MSG-1 + systemInformationAreaID BIT STRING (SIZE (24)) OPTIONAL, -- Need R + ... +} + +SchedulingInfo ::= SEQUENCE { + si-BroadcastStatus ENUMERATED {broadcasting, notBroadcasting}, + si-Periodicity ENUMERATED {rf8, rf16, rf32, rf64, rf128, rf256, rf512}, + sib-MappingInfo SIB-Mapping +} + +SIB-Mapping ::= SEQUENCE (SIZE (1..maxSIB)) OF SIB-TypeInfo + +SIB-TypeInfo ::= SEQUENCE { + type ENUMERATED {sibType2, sibType3, sibType4, sibType5, sibType6, sibType7, sibType8, sibType9, + sibType10-v1610, sibType11-v1610, sibType12-v1610, sibType13-v1610, sibType14-v1610, + spare3, spare2, spare1,... }, + valueTag INTEGER (0..31) OPTIONAL, -- Cond SIB-TYPE + areaScope ENUMERATED {true} OPTIONAL -- Need S +} + +-- TAG-SI-SCHEDULINGINFO-STOP +-- TAG-SKCOUNTER-START + +SK-Counter ::= INTEGER (0..65535) + +-- TAG-SKCOUNTER-STOP +-- TAG-SLOTFORMATCOMBINATIONSPERCELL-START + +SlotFormatCombinationsPerCell ::= SEQUENCE { + servingCellId ServCellIndex, + subcarrierSpacing SubcarrierSpacing, + subcarrierSpacing2 SubcarrierSpacing OPTIONAL, -- Need R + slotFormatCombinations SEQUENCE (SIZE (1..maxNrofSlotFormatCombinationsPerSet)) OF SlotFormatCombination + OPTIONAL, -- Need M + positionInDCI INTEGER(0..maxSFI-DCI-PayloadSize-1) OPTIONAL, -- Need M + ..., + [[ + enableConfiguredUL-r16 ENUMERATED {enabled} OPTIONAL -- Need R + ]] + +} + +SlotFormatCombination ::= SEQUENCE { + slotFormatCombinationId SlotFormatCombinationId, + slotFormats SEQUENCE (SIZE (1..maxNrofSlotFormatsPerCombination)) OF INTEGER (0..255) +} + +SlotFormatCombinationId ::= INTEGER (0..maxNrofSlotFormatCombinationsPerSet-1) + +-- TAG-SLOTFORMATCOMBINATIONSPERCELL-STOP +-- TAG-SLOTFORMATINDICATOR-START + +SlotFormatIndicator ::= SEQUENCE { + sfi-RNTI RNTI-Value, + dci-PayloadSize INTEGER (1..maxSFI-DCI-PayloadSize), + slotFormatCombToAddModList SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF SlotFormatCombinationsPerCell + OPTIONAL, -- Need N + slotFormatCombToReleaseList SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL, -- Need N + ..., + [[ + availableRB-SetsToAddModList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF AvailableRB-SetsPerCell-r16 OPTIONAL, -- Need N + availableRB-SetsToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL, -- Need N + switchTriggerToAddModList-r16 SEQUENCE (SIZE(1..4)) OF SearchSpaceSwitchTrigger-r16 OPTIONAL, -- Need N + switchTriggerToReleaseList-r16 SEQUENCE (SIZE(1..4)) OF ServCellIndex OPTIONAL, -- Need N + co-DurationsPerCellToAddModList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF CO-DurationsPerCell-r16 OPTIONAL, -- Need N + co-DurationsPerCellToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofAggregatedCellsPerCellGroup)) OF ServCellIndex OPTIONAL -- Need N + ]] +} + +CO-DurationsPerCell-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1), + subcarrierSpacing-r16 SubcarrierSpacing, + co-DurationList-r16 SEQUENCE (SIZE(1..64)) OF CO-Duration-r16 +} + +CO-Duration-r16 ::= INTEGER (0..1120) + +AvailableRB-SetsPerCell-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1) +} + +SearchSpaceSwitchTrigger-r16 ::= SEQUENCE { + servingCellId-r16 ServCellIndex, + positionInDCI-r16 INTEGER(0..maxSFI-DCI-PayloadSize-1) +} + +-- TAG-SLOTFORMATINDICATOR-STOP +-- TAG-S-NSSAI-START + +S-NSSAI ::= CHOICE{ + sst BIT STRING (SIZE (8)), + sst-SD BIT STRING (SIZE (32)) +} + +-- TAG-S-NSSAI-STOP +-- TAG-SPEEDSTATESCALEFACTORS-START + +SpeedStateScaleFactors ::= SEQUENCE { + sf-Medium ENUMERATED {oDot25, oDot5, oDot75, lDot0}, + sf-High ENUMERATED {oDot25, oDot5, oDot75, lDot0} +} +-- TAG-SPEEDSTATESCALEFACTORS-STOP +-- TAG-SPS-CONFIG-START + +SPS-Config ::= SEQUENCE { + periodicity ENUMERATED {ms10, ms20, ms32, ms40, ms64, ms80, ms128, ms160, ms320, ms640, + spare6, spare5, spare4, spare3, spare2, spare1}, + nrofHARQ-Processes INTEGER (1..8), + n1PUCCH-AN PUCCH-ResourceId OPTIONAL, -- Need M + mcs-Table ENUMERATED {qam64LowSE} OPTIONAL, -- Need S + ..., + [[ + sps-ConfigIndex-r16 SPS-ConfigIndex-r16 OPTIONAL, -- Cond SPS-List + harq-ProcID-Offset-r16 INTEGER (0..15) OPTIONAL, -- Need R + periodicityExt-r16 INTEGER (1..5120) OPTIONAL, -- Need R + harq-CodebookID-r16 INTEGER (1..2) OPTIONAL, -- Need R + pdsch-AggregationFactor-r16 ENUMERATED {n1, n2, n4, n8 } OPTIONAL -- Need S + ]] +} + +-- TAG-SPS-CONFIG-STOP +-- TAG-SPS-CONFIGINDEX-START + +SPS-ConfigIndex-r16 ::= INTEGER (0.. maxNrofSPS-Config-r16-1) + +-- TAG-SPS-CONFIGINDEX-STOP +-- TAG-SPS-PUCCH-AN-START + +SPS-PUCCH-AN-r16 ::= SEQUENCE { + sps-PUCCH-AN-ResourceID-r16 PUCCH-ResourceId, + maxPayloadSize-r16 INTEGER (4..256) OPTIONAL -- Need R +} + +-- TAG-SPS-PUCCH-AN-STOP +-- TAG-SPS-PUCCH-AN-LIST-START + +SPS-PUCCH-AN-List-r16 ::= SEQUENCE (SIZE(1..4)) OF SPS-PUCCH-AN-r16 + +-- TAG-SPS-PUCCH-AN-LIST-STOP +-- TAG-SRB-IDENTITY-START + +SRB-Identity ::= INTEGER (1..3) + +-- TAG-SRB-IDENTITY-STOP +-- TAG-SRS-CARRIERSWITCHING-START + +SRS-CarrierSwitching ::= SEQUENCE { + srs-SwitchFromServCellIndex INTEGER (0..31) OPTIONAL, -- Need M + srs-SwitchFromCarrier ENUMERATED {sUL, nUL}, + srs-TPC-PDCCH-Group CHOICE { + typeA SEQUENCE (SIZE (1..32)) OF SRS-TPC-PDCCH-Config, + typeB SRS-TPC-PDCCH-Config + } OPTIONAL, -- Need M + monitoringCells SEQUENCE (SIZE (1..maxNrofServingCells)) OF ServCellIndex OPTIONAL, -- Need M + ... +} + +SRS-TPC-PDCCH-Config ::= SEQUENCE { + srs-CC-SetIndexlist SEQUENCE (SIZE(1..4)) OF SRS-CC-SetIndex OPTIONAL -- Need M +} + +SRS-CC-SetIndex ::= SEQUENCE { + cc-SetIndex INTEGER (0..3) OPTIONAL, -- Need M + cc-IndexInOneCC-Set INTEGER (0..7) OPTIONAL -- Need M +} + +-- TAG-SRS-CARRIERSWITCHING-STOP +-- TAG-SRS-CONFIG-START + +SRS-Config ::= SEQUENCE { + srs-ResourceSetToReleaseList SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSetId OPTIONAL, -- Need N + srs-ResourceSetToAddModList SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSet OPTIONAL, -- Need N + srs-ResourceToReleaseList SEQUENCE (SIZE(1..maxNrofSRS-Resources)) OF SRS-ResourceId OPTIONAL, -- Need N + srs-ResourceToAddModList SEQUENCE (SIZE(1..maxNrofSRS-Resources)) OF SRS-Resource OPTIONAL, -- Need N + tpc-Accumulation ENUMERATED {disabled} OPTIONAL, -- Need S + ..., + [[ + srs-RequestDCI-1-2-r16 INTEGER (1..2) OPTIONAL, -- Need S + srs-RequestDCI-0-2-r16 INTEGER (1..2) OPTIONAL, -- Need S + srs-ResourceSetToAddModListDCI-0-2-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSet OPTIONAL, -- Need N + srs-ResourceSetToReleaseListDCI-0-2-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourceSets)) OF SRS-ResourceSetId OPTIONAL, -- Need N + srs-PosResourceSetToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResourceSets-r16)) OF SRS-PosResourceSetId-r16 + OPTIONAL, -- Need N + srs-PosResourceSetToAddModList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResourceSets-r16)) OF SRS-PosResourceSet-r16 OPTIONAL,-- Need N + srs-PosResourceToReleaseList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResources-r16)) OF SRS-PosResourceId-r16 OPTIONAL,-- Need N + srs-PosResourceToAddModList-r16 SEQUENCE (SIZE(1..maxNrofSRS-PosResources-r16)) OF SRS-PosResource-r16 OPTIONAL -- Need N + ]] +} + +SRS-ResourceSet ::= SEQUENCE { + srs-ResourceSetId SRS-ResourceSetId, + srs-ResourceIdList SEQUENCE (SIZE(1..maxNrofSRS-ResourcesPerSet)) OF SRS-ResourceId OPTIONAL, -- Cond Setup + resourceType CHOICE { + aperiodic SEQUENCE { + aperiodicSRS-ResourceTrigger INTEGER (1..maxNrofSRS-TriggerStates-1), + csi-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + slotOffset INTEGER (1..32) OPTIONAL, -- Need S + ..., + [[ + aperiodicSRS-ResourceTriggerList SEQUENCE (SIZE(1..maxNrofSRS-TriggerStates-2)) + OF INTEGER (1..maxNrofSRS-TriggerStates-1) OPTIONAL -- Need M + ]] + }, + semi-persistent SEQUENCE { + associatedCSI-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + ... + }, + periodic SEQUENCE { + associatedCSI-RS NZP-CSI-RS-ResourceId OPTIONAL, -- Cond NonCodebook + ... + } + }, + usage ENUMERATED {beamManagement, codebook, nonCodebook, antennaSwitching}, + alpha Alpha OPTIONAL, -- Need S + p0 INTEGER (-202..24) OPTIONAL, -- Cond Setup + pathlossReferenceRS PathlossReferenceRS-Config OPTIONAL, -- Need M + srs-PowerControlAdjustmentStates ENUMERATED { sameAsFci2, separateClosedLoop} OPTIONAL, -- Need S + ..., + [[ + pathlossReferenceRSList-r16 SetupRelease { PathlossReferenceRSList-r16} OPTIONAL -- Need M + ]] +} + +PathlossReferenceRS-Config ::= CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId +} + +PathlossReferenceRSList-r16 ::= SEQUENCE (SIZE (1..maxNrofSRS-PathlossReferenceRS-r16)) OF PathlossReferenceRS-r16 + +PathlossReferenceRS-r16 ::= SEQUENCE { + srs-PathlossReferenceRS-Id-r16 SRS-PathlossReferenceRS-Id-r16, + pathlossReferenceRS-r16 PathlossReferenceRS-Config +} + +SRS-PathlossReferenceRS-Id-r16 ::= INTEGER (0..maxNrofSRS-PathlossReferenceRS-1-r16) + +SRS-PosResourceSet-r16 ::= SEQUENCE { + srs-PosResourceSetId-r16 SRS-PosResourceSetId-r16, + srs-PosResourceIdList-r16 SEQUENCE (SIZE(1..maxNrofSRS-ResourcesPerSet)) OF SRS-PosResourceId-r16 + OPTIONAL, -- Cond Setup + resourceType-r16 CHOICE { + aperiodic-r16 SEQUENCE { + aperiodicSRS-ResourceTriggerList-r16 SEQUENCE (SIZE(1..maxNrofSRS-TriggerStates-1)) + OF INTEGER (1..maxNrofSRS-TriggerStates-1) OPTIONAL, -- Need M + ... + }, + semi-persistent-r16 SEQUENCE { + ... + }, + periodic-r16 SEQUENCE { + ... + } + }, + alpha-r16 Alpha OPTIONAL, -- Need S + p0-r16 INTEGER (-202..24) OPTIONAL, -- Cond Setup + pathlossReferenceRS-Pos-r16 CHOICE { + ssb-IndexServing-r16 SSB-Index, + ssb-Ncell-r16 SSB-InfoNcell-r16, + dl-PRS-r16 DL-PRS-Info-r16 + } OPTIONAL, -- Need M + ... +} + +SRS-ResourceSetId ::= INTEGER (0..maxNrofSRS-ResourceSets-1) + +SRS-PosResourceSetId-r16 ::= INTEGER (0..maxNrofSRS-PosResourceSets-1-r16) + +SRS-Resource ::= SEQUENCE { + srs-ResourceId SRS-ResourceId, + nrofSRS-Ports ENUMERATED {port1, ports2, ports4}, + ptrs-PortIndex ENUMERATED {n0, n1 } OPTIONAL, -- Need R + transmissionComb CHOICE { + n2 SEQUENCE { + combOffset-n2 INTEGER (0..1), + cyclicShift-n2 INTEGER (0..7) + }, + n4 SEQUENCE { + combOffset-n4 INTEGER (0..3), + cyclicShift-n4 INTEGER (0..11) + } + }, + resourceMapping SEQUENCE { + startPosition INTEGER (0..5), + nrofSymbols ENUMERATED {n1, n2, n4}, + repetitionFactor ENUMERATED {n1, n2, n4} + }, + freqDomainPosition INTEGER (0..67), + freqDomainShift INTEGER (0..268), + freqHopping SEQUENCE { + c-SRS INTEGER (0..63), + b-SRS INTEGER (0..3), + b-hop INTEGER (0..3) + }, + groupOrSequenceHopping ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceType CHOICE { + aperiodic SEQUENCE { + ... + }, + semi-persistent SEQUENCE { + periodicityAndOffset-sp SRS-PeriodicityAndOffset, + ... + }, + periodic SEQUENCE { + periodicityAndOffset-p SRS-PeriodicityAndOffset, + ... + } + }, + sequenceId INTEGER (0..1023), + spatialRelationInfo SRS-SpatialRelationInfo OPTIONAL, -- Need R + ..., + [[ + resourceMapping-r16 SEQUENCE { + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 ENUMERATED {n1, n2, n4}, + repetitionFactor-r16 ENUMERATED {n1, n2, n4} + } OPTIONAL -- Need R + ]] + +} + +SRS-PosResource-r16::= SEQUENCE { + srs-PosResourceId-r16 SRS-PosResourceId-r16, + transmissionComb-r16 CHOICE { + n2-r16 SEQUENCE { + combOffset-n2-r16 INTEGER (0..1), + cyclicShift-n2-r16 INTEGER (0..7) + }, + n4-r16 SEQUENCE { + combOffset-n4-16 INTEGER (0..3), + cyclicShift-n4-r16 INTEGER (0..11) + }, + n8-r16 SEQUENCE { + combOffset-n8-r16 INTEGER (0..7), + cyclicShift-n8-r16 INTEGER (0..5) + }, + ... + }, + resourceMapping-r16 SEQUENCE { + startPosition-r16 INTEGER (0..13), + nrofSymbols-r16 ENUMERATED {n1, n2, n4, n8, n12} + }, + freqDomainShift-r16 INTEGER (0..268), + freqHopping-r16 SEQUENCE { + c-SRS-r16 INTEGER (0..63), + ... + }, + groupOrSequenceHopping-r16 ENUMERATED { neither, groupHopping, sequenceHopping }, + resourceType-r16 CHOICE { + aperiodic-r16 SEQUENCE { + slotOffset-r16 INTEGER (1..32) OPTIONAL, -- Need S + ... + }, + semi-persistent-r16 SEQUENCE { + periodicityAndOffset-sp-r16 SRS-PeriodicityAndOffset-r16, + ... + }, + periodic-r16 SEQUENCE { + periodicityAndOffset-p-r16 SRS-PeriodicityAndOffset-r16, + ... + } + }, + sequenceId-r16 INTEGER (0..65535), + spatialRelationInfoPos-r16 SRS-SpatialRelationInfoPos-r16 OPTIONAL, -- Need R + ... +} + +SRS-SpatialRelationInfo ::= SEQUENCE { + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal CHOICE { + ssb-Index SSB-Index, + csi-RS-Index NZP-CSI-RS-ResourceId, + srs SEQUENCE { + resourceId SRS-ResourceId, + uplinkBWP BWP-Id + } + } +} + +SRS-SpatialRelationInfoPos-r16 ::= CHOICE { + servingRS-r16 SEQUENCE { + servingCellId ServCellIndex OPTIONAL, -- Need S + referenceSignal-r16 CHOICE { + ssb-IndexServing-r16 SSB-Index, + csi-RS-IndexServing-r16 NZP-CSI-RS-ResourceId, + srs-SpatialRelation-r16 SEQUENCE { + resourceSelection-r16 CHOICE { + srs-ResourceId-r16 SRS-ResourceId, + srs-PosResourceId-r16 SRS-PosResourceId-r16 + }, + uplinkBWP-r16 BWP-Id + } + } + }, + ssb-Ncell-r16 SSB-InfoNcell-r16, + dl-PRS-r16 DL-PRS-Info-r16 +} + +SSB-Configuration-r16 ::= SEQUENCE { + ssb-Freq-r16 ARFCN-ValueNR, + halfFrameIndex-r16 ENUMERATED {zero, one}, + ssbSubcarrierSpacing-r16 SubcarrierSpacing, + ssb-Periodicity-r16 ENUMERATED { ms5, ms10, ms20, ms40, ms80, ms160, spare2,spare1 } OPTIONAL, -- Need S + sfn0-Offset-r16 SEQUENCE { + sfn-Offset-r16 INTEGER (0..1023), + integerSubframeOffset-r16 INTEGER (0..9) OPTIONAL -- Need R + } OPTIONAL, -- Need R + sfn-SSB-Offset-r16 INTEGER (0..15), + ss-PBCH-BlockPower-r16 INTEGER (-60..50) OPTIONAL -- Cond Pathloss +} + +SSB-InfoNcell-r16 ::= SEQUENCE { + physicalCellId-r16 PhysCellId, + ssb-IndexNcell-r16 SSB-Index OPTIONAL, -- Need S + ssb-Configuration-r16 SSB-Configuration-r16 OPTIONAL -- Need S +} + +DL-PRS-Info-r16 ::= SEQUENCE { + dl-PRS-ID-r16 INTEGER (0..255), + dl-PRS-ResourceSetId-r16 INTEGER (0..7), + dl-PRS-ResourceId-r16 INTEGER (0..63) OPTIONAL -- Need S +} + +SRS-ResourceId ::= INTEGER (0..maxNrofSRS-Resources-1) +SRS-PosResourceId-r16 ::= INTEGER (0..maxNrofSRS-PosResources-1-r16) + +SRS-PeriodicityAndOffset ::= CHOICE { + sl1 NULL, + sl2 INTEGER(0..1), + sl4 INTEGER(0..3), + sl5 INTEGER(0..4), + sl8 INTEGER(0..7), + sl10 INTEGER(0..9), + sl16 INTEGER(0..15), + sl20 INTEGER(0..19), + sl32 INTEGER(0..31), + sl40 INTEGER(0..39), + sl64 INTEGER(0..63), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + sl640 INTEGER(0..639), + sl1280 INTEGER(0..1279), + sl2560 INTEGER(0..2559) +} + +SRS-PeriodicityAndOffset-r16 ::= CHOICE { + sl1 NULL, + sl2 INTEGER(0..1), + sl4 INTEGER(0..3), + sl5 INTEGER(0..4), + sl8 INTEGER(0..7), + sl10 INTEGER(0..9), + sl16 INTEGER(0..15), + sl20 INTEGER(0..19), + sl32 INTEGER(0..31), + sl40 INTEGER(0..39), + sl64 INTEGER(0..63), + sl80 INTEGER(0..79), + sl160 INTEGER(0..159), + sl320 INTEGER(0..319), + sl640 INTEGER(0..639), + sl1280 INTEGER(0..1279), + sl2560 INTEGER(0..2559), + sl5120 INTEGER(0..5119), + sl10240 INTEGER(0..10239), + sl40960 INTEGER(0..40959), + sl81920 INTEGER(0..81919), + ... +} + +-- TAG-SRS-CONFIG-STOP +-- TAG-SRS-RSRP-RANGE-START + +SRS-RSRP-Range-r16 ::= INTEGER(0..98) + +-- TAG-SRS-RSRP-RANGE-STOP +-- TAG-SRS-TPC-COMMANDCONFIG-START + +SRS-TPC-CommandConfig ::= SEQUENCE { + startingBitOfFormat2-3 INTEGER (1..31) OPTIONAL, -- Need R + fieldTypeFormat2-3 INTEGER (0..1) OPTIONAL, -- Need R + ..., + [[ + startingBitOfFormat2-3SUL INTEGER (1..31) OPTIONAL -- Need R + ]] +} + +-- TAG-SRS-TPC-COMMANDCONFIG-STOP +-- TAG-SSB-INDEX-START + +SSB-Index ::= INTEGER (0..maxNrofSSBs-1) + +-- TAG-SSB-INDEX-STOP +-- TAG-SSB-MTC-START + +SSB-MTC ::= SEQUENCE { + periodicityAndOffset CHOICE { + sf5 INTEGER (0..4), + sf10 INTEGER (0..9), + sf20 INTEGER (0..19), + sf40 INTEGER (0..39), + sf80 INTEGER (0..79), + sf160 INTEGER (0..159) + }, + duration ENUMERATED { sf1, sf2, sf3, sf4, sf5 } +} + +SSB-MTC2 ::= SEQUENCE { + pci-List SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need M + periodicity ENUMERATED {sf5, sf10, sf20, sf40, sf80, spare3, spare2, spare1} +} + +SSB-MTC2-LP-r16 ::= SEQUENCE { + pci-List SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need R + periodicity ENUMERATED {sf10, sf20, sf40, sf80, sf160, spare3, spare2, spare1} +} + +SSB-MTC3-r16 ::= SEQUENCE { + periodicityAndOffset-r16 CHOICE { + sf5-r16 INTEGER (0..4), + sf10-r16 INTEGER (0..9), + sf20-r16 INTEGER (0..19), + sf40-r16 INTEGER (0..39), + sf80-r16 INTEGER (0..79), + sf160-r16 INTEGER (0..159), + sf320-r16 INTEGER (0..319), + sf640-r16 INTEGER (0..639), + sf1280-r16 INTEGER (0..1279) + }, + duration-r16 ENUMERATED {sf1, sf2, sf3, sf4, sf5}, + pci-List-r16 SEQUENCE (SIZE (1..maxNrofPCIsPerSMTC)) OF PhysCellId OPTIONAL, -- Need M + ssb-ToMeasure-r16 SetupRelease { SSB-ToMeasure } OPTIONAL -- Need M +} + + +-- TAG-SSB-MTC-STOP +-- TAG-SSB-POSITIONQCL-RELATION-START + +SSB-PositionQCL-Relation-r16 ::= ENUMERATED {n1,n2,n4,n8} + +-- TAG-SSB-POSITIONQCL-RELATION-STOP +-- TAG-SSB-TOMEASURE-START + +SSB-ToMeasure ::= CHOICE { + shortBitmap BIT STRING (SIZE (4)), + mediumBitmap BIT STRING (SIZE (8)), + longBitmap BIT STRING (SIZE (64)) +} + +-- TAG-SSB-TOMEASURE-STOP +-- TAG-SS-RSSI-MEASUREMENT-START + +SS-RSSI-Measurement ::= SEQUENCE { + measurementSlots BIT STRING (SIZE (1..80)), + endSymbol INTEGER(0..3) +} + +-- TAG-SS-RSSI-MEASUREMENT-STOP +-- TAG-SUBCARRIERSPACING-START + +SubcarrierSpacing ::= ENUMERATED {kHz15, kHz30, kHz60, kHz120, kHz240, spare3, spare2, spare1} + +-- TAG-SUBCARRIERSPACING-STOP +-- TAG-TAG-CONFIG-START + +TAG-Config ::= SEQUENCE { + tag-ToReleaseList SEQUENCE (SIZE (1..maxNrofTAGs)) OF TAG-Id OPTIONAL, -- Need N + tag-ToAddModList SEQUENCE (SIZE (1..maxNrofTAGs)) OF TAG OPTIONAL -- Need N +} + +TAG ::= SEQUENCE { + tag-Id TAG-Id, + timeAlignmentTimer TimeAlignmentTimer, + ... +} + +TAG-Id ::= INTEGER (0..maxNrofTAGs-1) + +TimeAlignmentTimer ::= ENUMERATED {ms500, ms750, ms1280, ms1920, ms2560, ms5120, ms10240, infinity} + +-- TAG-TAG-CONFIG-STOP +-- TAG-TCI-STATE-START + +TCI-State ::= SEQUENCE { + tci-StateId TCI-StateId, + qcl-Type1 QCL-Info, + qcl-Type2 QCL-Info OPTIONAL, -- Need R + ... +} + +QCL-Info ::= SEQUENCE { + cell ServCellIndex OPTIONAL, -- Need R + bwp-Id BWP-Id OPTIONAL, -- Cond CSI-RS-Indicated + referenceSignal CHOICE { + csi-rs NZP-CSI-RS-ResourceId, + ssb SSB-Index + }, + qcl-Type ENUMERATED {typeA, typeB, typeC, typeD}, + ... +} + +-- TAG-TCI-STATE-STOP +-- TAG-TCI-STATEID-START + +TCI-StateId ::= INTEGER (0..maxNrofTCI-States-1) + +-- TAG-TCI-STATEID-STOP +-- TAG-TDD-UL-DL-CONFIGCOMMON-START + +TDD-UL-DL-ConfigCommon ::= SEQUENCE { + referenceSubcarrierSpacing SubcarrierSpacing, + pattern1 TDD-UL-DL-Pattern, + pattern2 TDD-UL-DL-Pattern OPTIONAL, -- Need R + ... +} + +TDD-UL-DL-Pattern ::= SEQUENCE { + dl-UL-TransmissionPeriodicity ENUMERATED {ms0p5, ms0p625, ms1, ms1p25, ms2, ms2p5, ms5, ms10}, + nrofDownlinkSlots INTEGER (0..maxNrofSlots), + nrofDownlinkSymbols INTEGER (0..maxNrofSymbols-1), + nrofUplinkSlots INTEGER (0..maxNrofSlots), + nrofUplinkSymbols INTEGER (0..maxNrofSymbols-1), + ..., + [[ + dl-UL-TransmissionPeriodicity-v1530 ENUMERATED {ms3, ms4} OPTIONAL -- Need R + ]] +} + +-- TAG-TDD-UL-DL-CONFIGCOMMON-STOP +-- TAG-TDD-UL-DL-CONFIGDEDICATED-START + +TDD-UL-DL-ConfigDedicated ::= SEQUENCE { + slotSpecificConfigurationsToAddModList SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotConfig OPTIONAL, -- Need N + slotSpecificConfigurationsToReleaseList SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotIndex OPTIONAL, -- Need N + ... +} + +TDD-UL-DL-ConfigDedicated-IAB-MT-r16::= SEQUENCE { + slotSpecificConfigurationsToAddModList-IAB-MT-r16 SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotConfig-IAB-MT-r16 OPTIONAL, -- Need N + slotSpecificConfigurationsToReleaseList-IAB-MT-r16 SEQUENCE (SIZE (1..maxNrofSlots)) OF TDD-UL-DL-SlotIndex OPTIONAL, -- Need N + ... +} + +TDD-UL-DL-SlotConfig ::= SEQUENCE { + slotIndex TDD-UL-DL-SlotIndex, + symbols CHOICE { + allDownlink NULL, + allUplink NULL, + explicit SEQUENCE { + nrofDownlinkSymbols INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need S + nrofUplinkSymbols INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need S + } + } +} + +TDD-UL-DL-SlotConfig-IAB-MT-r16::= SEQUENCE { + slotIndex-r16 TDD-UL-DL-SlotIndex, + symbols-IAB-MT-r16 CHOICE { + allDownlink-r16 NULL, + allUplink-r16 NULL, + explicit-r16 SEQUENCE { + nrofDownlinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need S + nrofUplinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need S + }, + explicit-IAB-MT-r16 SEQUENCE { + nrofDownlinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL, -- Need S + nrofUplinkSymbols-r16 INTEGER (1..maxNrofSymbols-1) OPTIONAL -- Need S + } + } +} + +TDD-UL-DL-SlotIndex ::= INTEGER (0..maxNrofSlots-1) + +-- TAG-TDD-UL-DL-CONFIGDEDICATED-STOP +-- TAG-TRACKINGAREACODE-START + +TrackingAreaCode ::= BIT STRING (SIZE (24)) + +-- TAG-TRACKINGAREACODE-STOP +-- TAG-TRESELECTION-START + +T-Reselection ::= INTEGER (0..7) + +-- TAG-TRESELECTION-STOP +-- TAG-TIMETOTRIGGER-START + +TimeToTrigger ::= ENUMERATED { + ms0, ms40, ms64, ms80, ms100, ms128, ms160, ms256, + ms320, ms480, ms512, ms640, ms1024, ms1280, ms2560, + ms5120} + +-- TAG-TIMETOTRIGGER-STOP +-- TAG-UAC-BARRINGINFOSETINDEX-START + +UAC-BarringInfoSetIndex ::= INTEGER (1..maxBarringInfoSet) + +-- TAG-UAC-BARRINGINFOSETINDEX-STOP +-- TAG-UAC-BARRINGINFOSETLIST-START + +UAC-BarringInfoSetList ::= SEQUENCE (SIZE(1..maxBarringInfoSet)) OF UAC-BarringInfoSet + +UAC-BarringInfoSet ::= SEQUENCE { + uac-BarringFactor ENUMERATED {p00, p05, p10, p15, p20, p25, p30, p40, + p50, p60, p70, p75, p80, p85, p90, p95}, + uac-BarringTime ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512}, + uac-BarringForAccessIdentity BIT STRING (SIZE(7)) +} + +-- TAG-UAC-BARRINGINFOSETLIST-STOP +-- TAG-UAC-BARRINGPERCATLIST-START + +UAC-BarringPerCatList ::= SEQUENCE (SIZE (1..maxAccessCat-1)) OF UAC-BarringPerCat + +UAC-BarringPerCat ::= SEQUENCE { + accessCategory INTEGER (1..maxAccessCat-1), + uac-barringInfoSetIndex UAC-BarringInfoSetIndex +} + +-- TAG-UAC-BARRINGPERCATLIST-STOP +-- TAG-UAC-BARRINGPERPLMN-LIST-START + +UAC-BarringPerPLMN-List ::= SEQUENCE (SIZE (1.. maxPLMN)) OF UAC-BarringPerPLMN + +UAC-BarringPerPLMN ::= SEQUENCE { + plmn-IdentityIndex INTEGER (1..maxPLMN), + uac-ACBarringListType CHOICE{ + uac-ImplicitACBarringList SEQUENCE (SIZE(maxAccessCat-1)) OF UAC-BarringInfoSetIndex, + uac-ExplicitACBarringList UAC-BarringPerCatList + } OPTIONAL -- Need S +} + +-- TAG-UAC-BARRINGPERPLMN-LIST-STOP +-- TAG-UE-TIMERSANDCONSTANTS-START + +UE-TimersAndConstants ::= SEQUENCE { + t300 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + t301 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + t310 ENUMERATED {ms0, ms50, ms100, ms200, ms500, ms1000, ms2000}, + n310 ENUMERATED {n1, n2, n3, n4, n6, n8, n10, n20}, + t311 ENUMERATED {ms1000, ms3000, ms5000, ms10000, ms15000, ms20000, ms30000}, + n311 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10}, + t319 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000}, + ... +} + +-- TAG-UE-TIMERSANDCONSTANTS-STOP +-- TAG-ULDELAYVALUECONFIG-START + +UL-DelayValueConfig-r16 ::= SEQUENCE { + delay-DRBlist SEQUENCE (SIZE(1..maxDRB)) OF DRB-Identity +} + +-- TAG-ULDELAYVALUECONFIG-STOP +-- TAG-UPLINKCANCELLATION-START + +UplinkCancellation-r16 ::= SEQUENCE { + ci-RNTI-r16 RNTI-Value, + dci-PayloadSizeForCI-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16), + ci-ConfigurationPerServingCell-r16 SEQUENCE (SIZE (1..maxNrofServingCells)) OF CI-ConfigurationPerServingCell-r16, + ... +} + +CI-ConfigurationPerServingCell-r16 ::= SEQUENCE { + servingCellId ServCellIndex, + positionInDCI-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16-1), + positionInDCI-ForSUL-r16 INTEGER (0..maxCI-DCI-PayloadSize-r16-1) OPTIONAL, -- Cond SUL-Only + ci-PayloadSize-r16 ENUMERATED {n1, n2, n4, n5, n7, n8, n10, n14, n16, n20, n28, n32, n35, n42, n56, n112}, + timeFrequencyRegion-r16 SEQUENCE { + timeDurationForCI-r16 ENUMERATED {n2, n4, n7, n14} OPTIONAL, -- Cond SymbolPeriodicity + timeGranularityForCI-r16 ENUMERATED {n1, n2, n4, n7, n14, n28}, + frequencyRegionForCI-r16 INTEGER (0..37949), + deltaOffset-r16 INTEGER (0..2), + ... + }, + uplinkCancellationPriority-v1610 ENUMERATED {enabled} OPTIONAL -- Need S +} + +-- TAG-UPLINKCANCELLATION-STOP +-- TAG-UPLINKCONFIGCOMMON-START + +UplinkConfigCommon ::= SEQUENCE { + frequencyInfoUL FrequencyInfoUL OPTIONAL, -- Cond InterFreqHOAndServCellAdd + initialUplinkBWP BWP-UplinkCommon OPTIONAL, -- Cond ServCellAdd + dummy TimeAlignmentTimer +} + +-- TAG-UPLINKCONFIGCOMMON-STOP +-- TAG-UPLINKCONFIGCOMMONSIB-START + +UplinkConfigCommonSIB ::= SEQUENCE { + frequencyInfoUL FrequencyInfoUL-SIB, + initialUplinkBWP BWP-UplinkCommon, + timeAlignmentTimerCommon TimeAlignmentTimer +} + +-- TAG-UPLINKCONFIGCOMMONSIB-STOP +-- TAG-UPLINKTXDIRECTCURRENTLIST-START + +UplinkTxDirectCurrentList ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF UplinkTxDirectCurrentCell + +UplinkTxDirectCurrentCell ::= SEQUENCE { + servCellIndex ServCellIndex, + uplinkDirectCurrentBWP SEQUENCE (SIZE (1..maxNrofBWPs)) OF UplinkTxDirectCurrentBWP, + ..., + [[ + uplinkDirectCurrentBWP-SUL SEQUENCE (SIZE (1..maxNrofBWPs)) OF UplinkTxDirectCurrentBWP OPTIONAL + ]] +} + +UplinkTxDirectCurrentBWP ::= SEQUENCE { + bwp-Id BWP-Id, + shift7dot5kHz BOOLEAN, + txDirectCurrentLocation INTEGER (0..3301) +} + +-- TAG-UPLINKTXDIRECTCURRENTLIST-STOP +-- TAG-UPLINKTXDIRECTCURRENTTWOCARRIERLIST-START + +UplinkTxDirectCurrentTwoCarrierList-r16 ::= SEQUENCE (SIZE (1..maxNrofTxDC-TwoCarrier-r16)) OF UplinkTxDirectCurrentTwoCarrier-r16 + +UplinkTxDirectCurrentTwoCarrier-r16 ::= SEQUENCE { + carrierOneInfo-r16 UplinkTxDirectCurrentCarrierInfo-r16, + carrierTwoInfo-r16 UplinkTxDirectCurrentCarrierInfo-r16, + singlePA-TxDirectCurrent-r16 UplinkTxDirectCurrentTwoCarrierInfo-r16, + secondPA-TxDirectCurrent-r16 UplinkTxDirectCurrentTwoCarrierInfo-r16 OPTIONAL +} + +UplinkTxDirectCurrentCarrierInfo-r16 ::= SEQUENCE { + servCellIndex-r16 ServCellIndex, + servCellInfo-r16 CHOICE { + bwp-Id-r16 BWP-Id, + deactivatedCarrier-r16 ENUMERATED {deactivated} + } +} + +UplinkTxDirectCurrentTwoCarrierInfo-r16 ::= SEQUENCE { + referenceCarrierIndex-r16 ServCellIndex, + shift7dot5kHz-r16 BOOLEAN, + txDirectCurrentLocation-r16 INTEGER (0..3301) +} + +-- TAG-UPLINKTXDIRECTCURRENTTWOCARRIERLIST-STOP +-- TAG-ZP-CSI-RS-RESOURCE-START + +ZP-CSI-RS-Resource ::= SEQUENCE { + zp-CSI-RS-ResourceId ZP-CSI-RS-ResourceId, + resourceMapping CSI-RS-ResourceMapping, + periodicityAndOffset CSI-ResourcePeriodicityAndOffset OPTIONAL, --Cond PeriodicOrSemiPersistent + ... +} + +ZP-CSI-RS-ResourceId ::= INTEGER (0..maxNrofZP-CSI-RS-Resources-1) + +-- TAG-ZP-CSI-RS-RESOURCE-STOP +-- TAG-ZP-CSI-RS-RESOURCESET-START + +ZP-CSI-RS-ResourceSet ::= SEQUENCE { + zp-CSI-RS-ResourceSetId ZP-CSI-RS-ResourceSetId, + zp-CSI-RS-ResourceIdList SEQUENCE (SIZE(1..maxNrofZP-CSI-RS-ResourcesPerSet)) OF ZP-CSI-RS-ResourceId, + ... +} + +-- TAG-ZP-CSI-RS-RESOURCESET-STOP +-- TAG-ZP-CSI-RS-RESOURCESETID-START + +ZP-CSI-RS-ResourceSetId ::= INTEGER (0..maxNrofZP-CSI-RS-ResourceSets-1) + +-- TAG-ZP-CSI-RS-RESOURCESETID-STOP +-- TAG-ACCESSSTRATUMRELEASE-START + +AccessStratumRelease ::= ENUMERATED { + rel15, rel16, spare6, spare5, spare4, spare3, spare2, spare1, ... } + +-- TAG-ACCESSSTRATUMRELEASE-STOP +-- TAG-BANDCOMBINATIONLIST-START + +BandCombinationList ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination + +BandCombinationList-v1540 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1540 + +BandCombinationList-v1550 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1550 + +BandCombinationList-v1560 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1560 + +BandCombinationList-v1570 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1570 + +BandCombinationList-v1580 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1580 + +BandCombinationList-v1590 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1590 + +BandCombinationList-v1610 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1610 + +BandCombinationList-v1630 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1630 + +BandCombinationList-v1640 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-v1640 + +BandCombinationList-UplinkTxSwitch-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-UplinkTxSwitch-r16 + +BandCombinationList-UplinkTxSwitch-v1630 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-UplinkTxSwitch-v1630 + +BandCombinationList-UplinkTxSwitch-v1640 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombination-UplinkTxSwitch-v1640 + +BandCombination ::= SEQUENCE { + bandList SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters, + featureSetCombination FeatureSetCombinationId, + ca-ParametersEUTRA CA-ParametersEUTRA OPTIONAL, + ca-ParametersNR CA-ParametersNR OPTIONAL, + mrdc-Parameters MRDC-Parameters OPTIONAL, + supportedBandwidthCombinationSet BIT STRING (SIZE (1..32)) OPTIONAL, + powerClass-v1530 ENUMERATED {pc2} OPTIONAL +} + +BandCombination-v1540::= SEQUENCE { + bandList-v1540 SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters-v1540, + ca-ParametersNR-v1540 CA-ParametersNR-v1540 OPTIONAL +} + +BandCombination-v1550 ::= SEQUENCE { + ca-ParametersNR-v1550 CA-ParametersNR-v1550 +} +BandCombination-v1560::= SEQUENCE { + ne-DC-BC ENUMERATED {supported} OPTIONAL, + ca-ParametersNRDC CA-ParametersNRDC OPTIONAL, + ca-ParametersEUTRA-v1560 CA-ParametersEUTRA-v1560 OPTIONAL, + ca-ParametersNR-v1560 CA-ParametersNR-v1560 OPTIONAL +} + +BandCombination-v1570 ::= SEQUENCE { + ca-ParametersEUTRA-v1570 CA-ParametersEUTRA-v1570 +} + +BandCombination-v1580 ::= SEQUENCE { + mrdc-Parameters-v1580 MRDC-Parameters-v1580 +} + +BandCombination-v1590::= SEQUENCE { + supportedBandwidthCombinationSetIntraENDC BIT STRING (SIZE (1..32)) OPTIONAL, + mrdc-Parameters-v1590 MRDC-Parameters-v1590 +} + +BandCombination-v1610 ::= SEQUENCE { + bandList-v1610 SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParameters-v1610 OPTIONAL, + ca-ParametersNR-v1610 CA-ParametersNR-v1610 OPTIONAL, + ca-ParametersNRDC-v1610 CA-ParametersNRDC-v1610 OPTIONAL, + powerClass-v1610 ENUMERATED {pc1dot5} OPTIONAL, + powerClassNRPart-r16 ENUMERATED {pc1, pc2, pc3, pc5} OPTIONAL, + featureSetCombinationDAPS-r16 FeatureSetCombinationId OPTIONAL, + mrdc-Parameters-v1620 MRDC-Parameters-v1620 OPTIONAL +} + +BandCombination-v1630 ::= SEQUENCE { + ca-ParametersNR-v1630 CA-ParametersNR-v1630 OPTIONAL, + ca-ParametersNRDC-v1630 CA-ParametersNRDC-v1630 OPTIONAL, + mrdc-Parameters-v1630 MRDC-Parameters-v1630 OPTIONAL, + supportedTxBandCombListPerBC-Sidelink-r16 BIT STRING (SIZE (1..maxBandComb)) OPTIONAL, + supportedRxBandCombListPerBC-Sidelink-r16 BIT STRING (SIZE (1..maxBandComb)) OPTIONAL, + scalingFactorTxSidelink-r16 SEQUENCE (SIZE (1..maxBandComb)) OF ScalingFactorSidelink-r16 OPTIONAL, + scalingFactorRxSidelink-r16 SEQUENCE (SIZE (1..maxBandComb)) OF ScalingFactorSidelink-r16 OPTIONAL +} + +BandCombination-v1640 ::= SEQUENCE { + ca-ParametersNR-v1640 CA-ParametersNR-v1640 OPTIONAL, + ca-ParametersNRDC-v1640 CA-ParametersNRDC-v1640 OPTIONAL +} + +BandCombination-UplinkTxSwitch-r16 ::= SEQUENCE { + bandCombination-r16 BandCombination, + bandCombination-v1540 BandCombination-v1540 OPTIONAL, + bandCombination-v1560 BandCombination-v1560 OPTIONAL, + bandCombination-v1570 BandCombination-v1570 OPTIONAL, + bandCombination-v1580 BandCombination-v1580 OPTIONAL, + bandCombination-v1590 BandCombination-v1590 OPTIONAL, + bandCombination-v1610 BandCombination-v1610 OPTIONAL, + supportedBandPairListNR-r16 SEQUENCE (SIZE (1..maxULTxSwitchingBandPairs)) OF ULTxSwitchingBandPair-r16, + uplinkTxSwitching-OptionSupport-r16 ENUMERATED {switchedUL, dualUL, both} OPTIONAL, + uplinkTxSwitching-PowerBoosting-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +BandCombination-UplinkTxSwitch-v1630 ::= SEQUENCE { + bandCombination-v1630 BandCombination-v1630 OPTIONAL +} + +BandCombination-UplinkTxSwitch-v1640 ::= SEQUENCE { + bandCombination-v1640 BandCombination-v1640 OPTIONAL +} + +ULTxSwitchingBandPair-r16 ::= SEQUENCE { + bandIndexUL1-r16 INTEGER(1..maxSimultaneousBands), + bandIndexUL2-r16 INTEGER(1..maxSimultaneousBands), + uplinkTxSwitchingPeriod-r16 ENUMERATED {n35us, n140us, n210us}, + uplinkTxSwitching-DL-Interruption-r16 BIT STRING (SIZE(1..maxSimultaneousBands)) OPTIONAL +} + +BandParameters ::= CHOICE { + eutra SEQUENCE { + bandEUTRA FreqBandIndicatorEUTRA, + ca-BandwidthClassDL-EUTRA CA-BandwidthClassEUTRA OPTIONAL, + ca-BandwidthClassUL-EUTRA CA-BandwidthClassEUTRA OPTIONAL + }, + nr SEQUENCE { + bandNR FreqBandIndicatorNR, + ca-BandwidthClassDL-NR CA-BandwidthClassNR OPTIONAL, + ca-BandwidthClassUL-NR CA-BandwidthClassNR OPTIONAL + } +} + +BandParameters-v1540 ::= SEQUENCE { + srs-CarrierSwitch CHOICE { + nr SEQUENCE { + srs-SwitchingTimesListNR SEQUENCE (SIZE (1..maxSimultaneousBands)) OF SRS-SwitchingTimeNR + }, + eutra SEQUENCE { + srs-SwitchingTimesListEUTRA SEQUENCE (SIZE (1..maxSimultaneousBands)) OF SRS-SwitchingTimeEUTRA + } + } OPTIONAL, + srs-TxSwitch SEQUENCE { + supportedSRS-TxPortSwitch ENUMERATED {t1r2, t1r4, t2r4, t1r4-t2r4, t1r1, t2r2, t4r4, notSupported}, + txSwitchImpactToRx INTEGER (1..32) OPTIONAL, + txSwitchWithAnotherBand INTEGER (1..32) OPTIONAL + } OPTIONAL +} + +BandParameters-v1610 ::= SEQUENCE { + srs-TxSwitch-v1610 SEQUENCE { + supportedSRS-TxPortSwitch-v1610 ENUMERATED {t1r1-t1r2, t1r1-t1r2-t1r4, t1r1-t1r2-t2r2-t2r4, t1r1-t1r2-t2r2-t1r4-t2r4, + t1r1-t2r2, t1r1-t2r2-t4r4} + } OPTIONAL +} + +ScalingFactorSidelink-r16 ::= ENUMERATED {f0p4, f0p75, f0p8, f1} + +-- TAG-BANDCOMBINATIONLIST-STOP +-- TAG-BANDCOMBINATIONLISTSIDELINKEUTRANR-START + +BandCombinationListSidelinkEUTRA-NR-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationParametersSidelinkEUTRA-NR-r16 + +BandCombinationListSidelinkEUTRA-NR-v1630 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationParametersSidelinkEUTRA-NR-v1630 + +BandCombinationParametersSidelinkEUTRA-NR-r16 ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParametersSidelinkEUTRA-NR-r16 + +BandCombinationParametersSidelinkEUTRA-NR-v1630 ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParametersSidelinkEUTRA-NR-v1630 + +BandParametersSidelinkEUTRA-NR-r16 ::= CHOICE { + eutra SEQUENCE { + bandParametersSidelinkEUTRA1-r16 OCTET STRING OPTIONAL, + bandParametersSidelinkEUTRA2-r16 OCTET STRING OPTIONAL + }, + nr SEQUENCE { + bandParametersSidelinkNR-r16 BandParametersSidelink-r16 + } +} + +BandParametersSidelinkEUTRA-NR-v1630 ::= CHOICE { + eutra NULL, + nr SEQUENCE { + tx-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + rx-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + sl-CrossCarrierScheduling-r16 ENUMERATED {supported} OPTIONAL + } +} + +BandParametersSidelink-r16 ::= SEQUENCE { + freqBandSidelink-r16 FreqBandIndicatorNR +} + +-- TAG-BANDCOMBINATIONLISTSIDELINKEUTRANR-STOP +-- TAG-CA-BANDWIDTHCLASSEUTRA-START + +CA-BandwidthClassEUTRA ::= ENUMERATED {a, b, c, d, e, f, ...} + +-- TAG-CA-BANDWIDTHCLASSEUTRA-STOP +-- TAG-CA-BANDWIDTHCLASSNR-START + +CA-BandwidthClassNR ::= ENUMERATED {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, ...} + +-- TAG-CA-BANDWIDTHCLASSNR-STOP +-- TAG-CA-PARAMETERSEUTRA-START + +CA-ParametersEUTRA ::= SEQUENCE { + multipleTimingAdvance ENUMERATED {supported} OPTIONAL, + simultaneousRx-Tx ENUMERATED {supported} OPTIONAL, + supportedNAICS-2CRS-AP BIT STRING (SIZE (1..8)) OPTIONAL, + additionalRx-Tx-PerformanceReq ENUMERATED {supported} OPTIONAL, + ue-CA-PowerClass-N ENUMERATED {class2} OPTIONAL, + supportedBandwidthCombinationSetEUTRA-v1530 BIT STRING (SIZE (1..32)) OPTIONAL, + ... +} + +CA-ParametersEUTRA-v1560 ::= SEQUENCE { + fd-MIMO-TotalWeightedLayers INTEGER (2..128) OPTIONAL +} + +CA-ParametersEUTRA-v1570 ::= SEQUENCE { + dl-1024QAM-TotalWeightedLayers INTEGER (0..10) OPTIONAL +} + +-- TAG-CA-PARAMETERSEUTRA-STOP +-- TAG-CA-PARAMETERSNR-START + +CA-ParametersNR ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL, + parallelTxSRS-PUCCH-PUSCH ENUMERATED {supported} OPTIONAL, + parallelTxPRACH-SRS-PUCCH-PUSCH ENUMERATED {supported} OPTIONAL, + simultaneousRxTxInterBandCA ENUMERATED {supported} OPTIONAL, + simultaneousRxTxSUL ENUMERATED {supported} OPTIONAL, + diffNumerologyAcrossPUCCH-Group ENUMERATED {supported} OPTIONAL, + diffNumerologyWithinPUCCH-GroupSmallerSCS ENUMERATED {supported} OPTIONAL, + supportedNumberTAG ENUMERATED {n2, n3, n4} OPTIONAL, + ... +} + +CA-ParametersNR-v1540 ::= SEQUENCE { + simultaneousSRS-AssocCSI-RS-AllCC INTEGER (5..32) OPTIONAL, + csi-RS-IM-ReceptionForFeedbackPerBandComb SEQUENCE { + maxNumberSimultaneousNZP-CSI-RS-ActBWP-AllCC INTEGER (1..64) OPTIONAL, + totalNumberPortsSimultaneousNZP-CSI-RS-ActBWP-AllCC INTEGER (2..256) OPTIONAL + } OPTIONAL, + simultaneousCSI-ReportsAllCC INTEGER (5..32) OPTIONAL, + dualPA-Architecture ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1550 ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1560 ::= SEQUENCE { + diffNumerologyWithinPUCCH-GroupLargerSCS ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1610 ::= SEQUENCE { + -- R1 9-3: Parallel MsgA and SRS/PUCCH/PUSCH transmissions across CCs in inter-band CA + parallelTxMsgA-SRS-PUCCH-PUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 9-4: MsgA operation in a band combination including SUL + msgA-SUL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9c: Joint search space group switching across multiple cells + jointSearchSpaceGroupSwitchingAcrossCells-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-5: Half-duplex UE behaviour in TDD CA for same SCS + half-DuplexTDD-CA-SameSCS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-4: SCell dormancy within active time + scellDormancyWithinActiveTime-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-4a: SCell dormancy outside active time + scellDormancyOutsideActiveTime-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-6: Cross-carrier A-CSI RS triggering with different SCS + crossCarrierA-CSI-trigDiffSCS-r16 ENUMERATED {higherA-CSI-SCS,lowerA-CSI-SCS,both} OPTIONAL, + -- R1 18-6a: Default QCL assumption for cross-carrier A-CSI-RS triggering + defaultQCL-CrossCarrierA-CSI-Trig-r16 ENUMERATED {diffOnly, both} OPTIONAL, + -- R1 18-7: CA with non-aligned frame boundaries for inter-band CA + interCA-NonAlignedFrame-r16 ENUMERATED {supported} OPTIONAL, + simul-SRS-Trans-BC-r16 ENUMERATED {n2} OPTIONAL, + interFreqDAPS-r16 SEQUENCE { + interFreqAsyncDAPS-r16 ENUMERATED {supported} OPTIONAL, + interFreqDiffSCS-DAPS-r16 ENUMERATED {supported} OPTIONAL, + interFreqMultiUL-TransmissionDAPS-r16 ENUMERATED {supported} OPTIONAL, + interFreqSemiStaticPowerSharingDAPS-Mode1-r16 ENUMERATED {supported} OPTIONAL, + interFreqSemiStaticPowerSharingDAPS-Mode2-r16 ENUMERATED {supported} OPTIONAL, + interFreqDynamicPowerSharingDAPS-r16 ENUMERATED {short, long} OPTIONAL, + interFreqUL-TransCancellationDAPS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + codebookParametersPerBC-r16 CodebookParameters-v1610 OPTIONAL, + -- R1 16-2a-10 Value of R for BD/CCE + blindDetectFactor-r16 INTEGER (1..2) OPTIONAL, + -- R1 11-2a: Capability on the number of CCs for monitoring a maximum number of BDs and non-overlapped CCEs per span when configured + -- with DL CA with Rel-16 PDCCH monitoring capability on all the serving cells + pdcch-MonitoringCA-r16 SEQUENCE { + maxNumberOfMonitoringCC-r16 INTEGER (2..16), + supportedSpanArrangement-r16 ENUMERATED {alignedOnly, alignedAndNonAligned} + } OPTIONAL, + -- R1 11-2c: Number of carriers for CCE/BD scaling with DL CA with mix of Rel. 16 and Rel. 15 PDCCH monitoring capabilities on + -- different carriers + pdcch-BlindDetectionCA-Mixed-r16 SEQUENCE { + pdcch-BlindDetectionCA1-r16 INTEGER (1..15), + pdcch-BlindDetectionCA2-r16 INTEGER (1..15), + supportedSpanArrangement-r16 ENUMERATED {alignedOnly, alignedAndNonAligned} + } OPTIONAL, + -- R1 11-2d: Capability on the number of CCs for monitoring a maximum number of BDs and non-overlapped CCEs per span for MCG and for + -- SCG when configured for NR-DC operation with Rel-16 PDCCH monitoring capability on all the serving cells + pdcch-BlindDetectionMCG-UE-r16 INTEGER (1..14) OPTIONAL, + pdcch-BlindDetectionSCG-UE-r16 INTEGER (1..14) OPTIONAL, + -- R1 11-2e: Number of carriers for CCE/BD scaling for MCG and for SCG when configured for NR-DC operation with mix of Rel. 16 and + -- Rel. 15 PDCCH monitoring capabilities on different carriers + pdcch-BlindDetectionMCG-UE-Mixed-r16 SEQUENCE { + pdcch-BlindDetectionMCG-UE1-r16 INTEGER (0..15), + pdcch-BlindDetectionMCG-UE2-r16 INTEGER (0..15) + } OPTIONAL, + pdcch-BlindDetectionSCG-UE-Mixed-r16 SEQUENCE { + pdcch-BlindDetectionSCG-UE1-r16 INTEGER (0..15), + pdcch-BlindDetectionSCG-UE2-r16 INTEGER (0..15) + } OPTIONAL, + -- R1 18-5 cross-carrier scheduling with different SCS in DL CA + crossCarrierSchedulingDL-DiffSCS-r16 ENUMERATED {low-to-high, high-to-low, both} OPTIONAL, + -- R1 18-5a Default QCL assumption for cross-carrier scheduling + crossCarrierSchedulingDefaultQCL-r16 ENUMERATED {diff-only, both} OPTIONAL, + -- R1 18-5b cross-carrier scheduling with different SCS in UL CA + crossCarrierSchedulingUL-DiffSCS-r16 ENUMERATED {low-to-high, high-to-low, both} OPTIONAL, + -- R1 13.19a Simultaneous positioning SRS and MIMO SRS transmission for a given BC + simul-SRS-MIMO-Trans-BC-r16 ENUMERATED {n2} OPTIONAL, + -- R1 16-3a, 16-3a-1, 16-3b, 16-3b-1: New Individual Codebook + codebookParametersAdditionPerBC-r16 CodebookParametersAdditionPerBC-r16 OPTIONAL, + -- R1 16-8: Mixed codebook + codebookComboParametersAdditionPerBC-r16 CodebookComboParametersAdditionPerBC-r16 OPTIONAL +} + +CA-ParametersNR-v1630 ::= SEQUENCE { + -- R1 22-5b: Simultaneous transmission of SRS for antenna switching and SRS for CB/NCB /BM for inter-band UL CA + -- R1 22-5d: Simultaneous transmission of SRS for antenna switching for inter-band UL CA + simulTX-SRS-AntSwitchingInterBandUL-CA-r16 SimulSRS-ForAntennaSwitching-r16 OPTIONAL, + -- R4 8-5: supported beam management type for inter-band CA + beamManagementType-r16 ENUMERATED {ibm, cbm} OPTIONAL, + -- R4 7-3a: UL frequency separation class with aggregate BW and Gap BW + intraBandFreqSeparationUL-AggBW-GapBW-r16 ENUMERATED {classI, classII, classIII} OPTIONAL, + -- RAN 89: Case B in case of Inter-band CA with non-aligned frame boundaries + interCA-NonAlignedFrame-B-r16 ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNR-v1640 ::= SEQUENCE { + -- R4 7-5: Support of reporting UL Tx DC locations for uplink intra-band CA. + uplinkTxDC-TwoCarrierReport-r16 ENUMERATED {supported} OPTIONAL, + -- RAN 22-6: Support of up to 3 different numerologies in the same NR PUCCH group for NR part of EN-DC, NGEN-DC, NE-DC and NR-CA + -- where UE is not configured with two NR PUCCH groups + maxUpTo3Diff-NumerologiesConfigSinglePUCCH-grp-r16 PUCCH-Grp-CarrierTypes-r16 OPTIONAL, + -- RAN 22-6a: Support of up to 4 different numerologies in the same NR PUCCH group for NR part of EN-DC, NGEN-DC, NE-DC and NR-CA + -- where UE is not configured with two NR PUCCH groups + maxUpTo4Diff-NumerologiesConfigSinglePUCCH-grp-r16 PUCCH-Grp-CarrierTypes-r16 OPTIONAL, + -- RAN 22-7: Support two PUCCH groups for NR-CA with 3 or more bands with at least two carrier types + twoPUCCH-Grp-ConfigurationsList-r16 SEQUENCE (SIZE (1..maxTwoPUCCH-Grp-ConfigList-r16)) OF TwoPUCCH-Grp-Configurations-r16 OPTIONAL, + -- R1 22-7a: Different numerology across NR PUCCH groups + diffNumerologyAcrossPUCCH-Group-CarrierTypes-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-7b: Different numerologies across NR carriers within the same NR PUCCH group, with PUCCH on a carrier of smaller SCS + diffNumerologyWithinPUCCH-GroupSmallerSCS-CarrierTypes-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-7c: Different numerologies across NR carriers within the same NR PUCCH group, with PUCCH on a carrier of larger SCS + diffNumerologyWithinPUCCH-GroupLargerSCS-CarrierTypes-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-2f: add the replicated FGs of 11-2a/c with restriction for non-aligned span case + -- with DL CA with Rel-16 PDCCH monitoring capability on all the serving cells + pdcch-MonitoringCA-NonAlignedSpan-r16 INTEGER (2..16) OPTIONAL, + -- R1 11-2g: add the replicated FGs of 11-2a/c with restriction for non-aligned span case + pdcch-BlindDetectionCA-Mixed-NonAlignedSpan-r16 SEQUENCE { + pdcch-BlindDetectionCA1-r16 INTEGER (1..15), + pdcch-BlindDetectionCA2-r16 INTEGER (1..15) + } OPTIONAL +} + +SimulSRS-ForAntennaSwitching-r16 ::= SEQUENCE { + supportSRS-xTyR-xLessThanY-r16 ENUMERATED {supported} OPTIONAL, + supportSRS-xTyR-xEqualToY-r16 ENUMERATED {supported} OPTIONAL, + supportSRS-AntennaSwitching-r16 ENUMERATED {supported} OPTIONAL +} + +TwoPUCCH-Grp-Configurations-r16 ::= SEQUENCE { + pucch-PrimaryGroupMapping-r16 TwoPUCCH-Grp-ConfigParams-r16, + pucch-SecondaryGroupMapping-r16 TwoPUCCH-Grp-ConfigParams-r16 +} + +TwoPUCCH-Grp-ConfigParams-r16 ::= SEQUENCE { + pucch-GroupMapping-r16 PUCCH-Grp-CarrierTypes-r16, + pucch-TX-r16 PUCCH-Grp-CarrierTypes-r16 +} + +PUCCH-Grp-CarrierTypes-r16 ::= SEQUENCE { + fr1-NonSharedTDD-r16 ENUMERATED {supported} OPTIONAL, + fr1-SharedTDD-r16 ENUMERATED {supported} OPTIONAL, + fr1-NonSharedFDD-r16 ENUMERATED {supported} OPTIONAL, + fr2-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-CA-PARAMETERSNR-STOP +-- TAG-CA-PARAMETERS-NRDC-START + +CA-ParametersNRDC ::= SEQUENCE { + ca-ParametersNR-ForDC CA-ParametersNR OPTIONAL, + ca-ParametersNR-ForDC-v1540 CA-ParametersNR-v1540 OPTIONAL, + ca-ParametersNR-ForDC-v1550 CA-ParametersNR-v1550 OPTIONAL, + ca-ParametersNR-ForDC-v1560 CA-ParametersNR-v1560 OPTIONAL, + featureSetCombinationDC FeatureSetCombinationId OPTIONAL +} + +CA-ParametersNRDC-v1610 ::= SEQUENCE { + -- R1 18-1: Semi-static power sharing mode1 between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-PwrSharingMode1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-1a: Semi-static power sharing mode 2 between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-PwrSharingMode2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-1b: Dynamic power sharing between MCG and SCG cells of same FR for NR dual connectivity + intraFR-NR-DC-DynamicPwrSharing-r16 ENUMERATED {short, long} OPTIONAL, + asyncNRDC-r16 ENUMERATED {supported} OPTIONAL +} + +CA-ParametersNRDC-v1630 ::= SEQUENCE { + ca-ParametersNR-ForDC-v1610 CA-ParametersNR-v1610 OPTIONAL, + ca-ParametersNR-ForDC-v1630 CA-ParametersNR-v1630 OPTIONAL +} + +CA-ParametersNRDC-v1640 ::= SEQUENCE { + ca-ParametersNR-ForDC-v1640 CA-ParametersNR-v1640 OPTIONAL +} + +-- TAG-CA-PARAMETERS-NRDC-STOP +-- TAG-CARRIERAGGREGATIONVARIANT-START + +CarrierAggregationVariant ::= SEQUENCE { + fr1fdd-FR1TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR2TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL, + fr1tdd-FR2TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1tdd-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR1FDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR1TDD ENUMERATED {supported} OPTIONAL, + fr1fdd-FR1TDD-FR2TDD-CA-SpCellOnFR2TDD ENUMERATED {supported} OPTIONAL +} + +-- TAG-CARRIERAGGREGATIONVARIANT-STOP +-- TAG-CODEBOOKPARAMETERS-START + +CodebookParameters ::= SEQUENCE { + type1 SEQUENCE { + singlePanel SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + modes ENUMERATED {mode1, mode1andMode2}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) + }, + multiPanel SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + modes ENUMERATED {mode1, mode2, both}, + nrofPanels ENUMERATED {n2, n4}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) + } OPTIONAL + }, + type2 SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + amplitudeSubsetRestriction ENUMERATED {supported} OPTIONAL + } OPTIONAL, + type2-PortSelection SEQUENCE { + supportedCSI-RS-ResourceList SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource, + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband} + } OPTIONAL +} + +CodebookParameters-v1610 ::= SEQUENCE { + supportedCSI-RS-ResourceListAlt-r16 SEQUENCE { + type1-SinglePanel-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type1-MultiPanel-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type2-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL, + type2-PortSelection-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-Resources)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) OPTIONAL + } OPTIONAL +} + +CodebookParametersAddition-r16 ::= SEQUENCE { + etype2-r16 SEQUENCE { + -- R1 16-3a Regular eType 2 R=1 + etype2R1-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF + INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + }, + -- R1 16-3a-1 Regular eType 2 R=2 + etype2R2-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF + INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + -- R1 16-3a-2: Support of parameter combinations 7-8 + paramComb7-8-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-3a-3: Support of rank 3,4 + rank3-4-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-3a-4: CBSR with soft amplitude restriction + amplitudeSubsetRestriction-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + etype2-PS-r16 SEQUENCE { + -- R1 16-3b Regular eType 2 R=1 PortSelection + etype2R1-PortSelection-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF + INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + }, + -- R1 16-3b-1 Regular eType 2 R=2 PortSelection + etype2R2-PortSelection-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF + INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + -- R1 16-3b-2: Support of rank 3,4 + rank3-4-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL +} + +CodebookComboParametersAddition-r16 ::= SEQUENCE { + -- R1 16-8 Mixed codebook types + type1SP-Type2-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-Type2PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-eType2R1-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-eType2R2-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-eType2R1PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-eType2R2PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1SP-Type2-Type2PS-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-Type2-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-Type2PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-eType2R1-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-eType2R2-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-eType2R1PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-eType2R2PS-null-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL, + type1MP-Type2-Type2PS-r16 SEQUENCE { + supportedCSI-RS-ResourceListAdd-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + } OPTIONAL +} + +CodebookParametersAdditionPerBC-r16::= SEQUENCE { + -- R1 16-3a Regular eType 2 R=1 + etype2R1-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + -- R1 16-3a-1 Regular eType 2 R=2 + etype2R2-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + -- R1 16-3b Regular eType 2 R=1 PortSelection + etype2R1-PortSelection-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + -- R1 16-3b-1 Regular eType 2 R=2 PortSelection + etype2R2-PortSelection-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL +} + +CodebookComboParametersAdditionPerBC-r16::= SEQUENCE { + -- R1 16-8 Mixed codebook types + type1SP-Type2-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-Type2PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-eType2R1-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-eType2R2-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-eType2R1PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-eType2R2PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1SP-Type2-Type2PS-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-Type2-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-Type2PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-eType2R1-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-eType2R2-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-eType2R1PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-eType2R2PS-null-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL, + type1MP-Type2-Type2PS-r16 SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesExt-r16)) OF INTEGER (0..maxNrofCSI-RS-ResourcesAlt-1-r16) + OPTIONAL +} + +CodebookVariantsList-r16 ::= SEQUENCE (SIZE (1..maxNrofCSI-RS-ResourcesAlt-r16)) OF SupportedCSI-RS-Resource + +SupportedCSI-RS-Resource ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p2, p4, p8, p12, p16, p24, p32}, + maxNumberResourcesPerBand INTEGER (1..64), + totalNumberTxPortsPerBand INTEGER (2..256) +} + +-- TAG-CODEBOOKPARAMETERS-STOP +-- TAG-FEATURESETCOMBINATION-START + +FeatureSetCombination ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF FeatureSetsPerBand + +FeatureSetsPerBand ::= SEQUENCE (SIZE (1..maxFeatureSetsPerBand)) OF FeatureSet + +FeatureSet ::= CHOICE { + eutra SEQUENCE { + downlinkSetEUTRA FeatureSetEUTRA-DownlinkId, + uplinkSetEUTRA FeatureSetEUTRA-UplinkId + }, + nr SEQUENCE { + downlinkSetNR FeatureSetDownlinkId, + uplinkSetNR FeatureSetUplinkId + } +} + +-- TAG-FEATURESETCOMBINATION-STOP +-- TAG-FEATURESETCOMBINATIONID-START + +FeatureSetCombinationId ::= INTEGER (0.. maxFeatureSetCombinations) + +-- TAG-FEATURESETCOMBINATIONID-STOP +-- TAG-FEATURESETDOWNLINK-START + +FeatureSetDownlink ::= SEQUENCE { + featureSetListPerDownlinkCC SEQUENCE (SIZE (1..maxNrofServingCells)) OF FeatureSetDownlinkPerCC-Id, + + intraBandFreqSeparationDL FreqSeparationClass OPTIONAL, + scalingFactor ENUMERATED {f0p4, f0p75, f0p8} OPTIONAL, + dummy8 ENUMERATED {supported} OPTIONAL, + scellWithoutSSB ENUMERATED {supported} OPTIONAL, + csi-RS-MeasSCellWithoutSSB ENUMERATED {supported} OPTIONAL, + dummy1 ENUMERATED {supported} OPTIONAL, + type1-3-CSS ENUMERATED {supported} OPTIONAL, + pdcch-MonitoringAnyOccasions ENUMERATED {withoutDCI-Gap, withDCI-Gap} OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + ue-SpecificUL-DL-Assignment ENUMERATED {supported} OPTIONAL, + searchSpaceSharingCA-DL ENUMERATED {supported} OPTIONAL, + timeDurationForQCL SEQUENCE { + scs-60kHz ENUMERATED {s7, s14, s28} OPTIONAL, + scs-120kHz ENUMERATED {s14, s28} OPTIONAL + } OPTIONAL, + pdsch-ProcessingType1-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + dummy3 DummyA OPTIONAL, + dummy4 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyB OPTIONAL, + dummy5 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyC OPTIONAL, + dummy6 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyD OPTIONAL, + dummy7 SEQUENCE (SIZE (1.. maxNrofCodebooks)) OF DummyE OPTIONAL +} + +FeatureSetDownlink-v1540 ::= SEQUENCE { + oneFL-DMRS-TwoAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + additionalDMRS-DL-Alt ENUMERATED {supported} OPTIONAL, + twoFL-DMRS-TwoAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-ThreeAdditionalDMRS-DL ENUMERATED {supported} OPTIONAL, + pdcch-MonitoringAnyOccasionsWithSpanGap SEQUENCE { + scs-15kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-30kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-60kHz ENUMERATED {set1, set2, set3} OPTIONAL, + scs-120kHz ENUMERATED {set1, set2, set3} OPTIONAL + } OPTIONAL, + pdsch-SeparationWithGap ENUMERATED {supported} OPTIONAL, + pdsch-ProcessingType2 SEQUENCE { + scs-15kHz ProcessingParameters OPTIONAL, + scs-30kHz ProcessingParameters OPTIONAL, + scs-60kHz ProcessingParameters OPTIONAL + } OPTIONAL, + pdsch-ProcessingType2-Limited SEQUENCE { + differentTB-PerSlot-SCS-30kHz ENUMERATED {upto1, upto2, upto4, upto7} + } OPTIONAL, + dl-MCS-TableAlt-DynamicIndication ENUMERATED {supported} OPTIONAL +} + +FeatureSetDownlink-v15a0 ::= SEQUENCE { + supportedSRS-Resources SRS-Resources OPTIONAL +} + +FeatureSetDownlink-v1610 ::= SEQUENCE { + -- R1 22-4e/4f/4g/4h: CBG based reception for DL with unicast PDSCH(s) per slot per CC with UE processing time Capability 1 + cbgPDSCH-ProcessingType1-DifferentTB-PerSlot-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-30kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-60kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-120kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + + -- R1 22-3e/3f/3g/3h: CBG based reception for DL with unicast PDSCH(s) per slot per CC with UE processing time Capability 2 + cbgPDSCH-ProcessingType2-DifferentTB-PerSlot-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-30kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-60kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL, + scs-120kHz-r16 ENUMERATED {one, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + intraFreqDAPS-r16 SEQUENCE { + intraFreqDiffSCS-DAPS-r16 ENUMERATED {supported} OPTIONAL, + intraFreqAsyncDAPS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + intraBandFreqSeparationDL-v1620 FreqSeparationClassDL-v1620 OPTIONAL, + intraBandFreqSeparationDL-Only-r16 FreqSeparationClassDL-Only-r16 OPTIONAL, + + -- R1 11-2: Rel-16 PDCCH monitoring capability + pdcch-Monitoring-r16 SEQUENCE { + pdsch-ProcessingType1-r16 SEQUENCE { + scs-15kHz-r16 PDCCH-MonitoringOccasions-r16 OPTIONAL, + scs-30kHz-r16 PDCCH-MonitoringOccasions-r16 OPTIONAL + } OPTIONAL, + pdsch-ProcessingType2-r16 SEQUENCE { + scs-15kHz-r16 PDCCH-MonitoringOccasions-r16 OPTIONAL, + scs-30kHz-r16 PDCCH-MonitoringOccasions-r16 OPTIONAL + } OPTIONAL + } OPTIONAL, + + -- R1 11-2b: Mix of Rel. 16 PDCCH monitoring capability and Rel. 15 PDCCH monitoring capability on different carriers + pdcch-MonitoringMixed-r16 ENUMERATED {supported} OPTIONAL, + + -- R1 18-5c: Processing up to X unicast DCI scheduling for DL per scheduled CC + crossCarrierSchedulingProcessing-DiffSCS-r16 SEQUENCE { + scs-15kHz-120kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-15kHz-60kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-30kHz-120kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-15kHz-30kHz-r16 ENUMERATED {n2} OPTIONAL, + scs-30kHz-60kHz-r16 ENUMERATED {n2} OPTIONAL, + scs-60kHz-120kHz-r16 ENUMERATED {n2} OPTIONAL + } OPTIONAL, + + -- R1 16-2b-1: Support of single-DCI based SDM scheme + singleDCI-SDM-scheme-r16 ENUMERATED {supported} OPTIONAL +} + +PDCCH-MonitoringOccasions-r16 ::= SEQUENCE { + period7span3-r16 ENUMERATED {supported} OPTIONAL, + period4span3-r16 ENUMERATED {supported} OPTIONAL, + period2span2-r16 ENUMERATED {supported} OPTIONAL +} + +DummyA ::= SEQUENCE { + maxNumberNZP-CSI-RS-PerCC INTEGER (1..32), + maxNumberPortsAcrossNZP-CSI-RS-PerCC ENUMERATED {p2, p4, p8, p12, p16, p24, p32, p40, p48, p56, p64, p72, p80, + p88, p96, p104, p112, p120, p128, p136, p144, p152, p160, p168, + p176, p184, p192, p200, p208, p216, p224, p232, p240, p248, p256}, + maxNumberCS-IM-PerCC ENUMERATED {n1, n2, n4, n8, n16, n32}, + maxNumberSimultaneousCSI-RS-ActBWP-AllCC ENUMERATED {n5, n6, n7, n8, n9, n10, n12, n14, n16, n18, n20, n22, n24, n26, + n28, n30, n32, n34, n36, n38, n40, n42, n44, n46, n48, n50, n52, + n54, n56, n58, n60, n62, n64}, + totalNumberPortsSimultaneousCSI-RS-ActBWP-AllCC ENUMERATED {p8, p12, p16, p24, p32, p40, p48, p56, p64, p72, p80, + p88, p96, p104, p112, p120, p128, p136, p144, p152, p160, p168, + p176, p184, p192, p200, p208, p216, p224, p232, p240, p248, p256} +} + +DummyB ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p2, p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + supportedCodebookMode ENUMERATED {mode1, mode1AndMode2}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyC ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p8, p16, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + supportedCodebookMode ENUMERATED {mode1, mode2, both}, + supportedNumberPanels ENUMERATED {n2, n4}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyD ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + amplitudeSubsetRestriction ENUMERATED {supported} OPTIONAL, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +DummyE ::= SEQUENCE { + maxNumberTxPortsPerResource ENUMERATED {p4, p8, p12, p16, p24, p32}, + maxNumberResources INTEGER (1..64), + totalNumberTxPorts INTEGER (2..256), + parameterLx INTEGER (2..4), + amplitudeScalingType ENUMERATED {wideband, widebandAndSubband}, + maxNumberCSI-RS-PerResourceSet INTEGER (1..8) +} + +-- TAG-FEATURESETDOWNLINK-STOP +-- TAG-FEATURESETDOWNLINKID-START + +FeatureSetDownlinkId ::= INTEGER (0..maxDownlinkFeatureSets) + +-- TAG-FEATURESETDOWNLINKID-STOP +-- TAG-FEATURESETDOWNLINKPERCC-START + +FeatureSetDownlinkPerCC ::= SEQUENCE { + supportedSubcarrierSpacingDL SubcarrierSpacing, + supportedBandwidthDL SupportedBandwidth, + channelBW-90mhz ENUMERATED {supported} OPTIONAL, + maxNumberMIMO-LayersPDSCH MIMO-LayersDL OPTIONAL, + supportedModulationOrderDL ModulationOrder OPTIONAL +} + +FeatureSetDownlinkPerCC-v1620 ::= SEQUENCE { + -- R1 16-2a: Mulit-DCI based multi-TRP + multiDCI-MultiTRP-r16 MultiDCI-MultiTRP-r16 OPTIONAL, + -- R1 16-2b-3: Support of single-DCI based FDMSchemeB + supportFDM-SchemeB-r16 ENUMERATED {supported} OPTIONAL +} + +MultiDCI-MultiTRP-r16 ::= SEQUENCE { + maxNumberCORESET-r16 ENUMERATED {n2, n3, n4, n5}, + maxNumberCORESETPerPoolIndex-r16 INTEGER (1..3), + maxNumberUnicastPDSCH-PerPool-r16 ENUMERATED {n1, n2, n3, n4, n7} +} + +-- TAG-FEATURESETDOWNLINKPERCC-STOP +-- TAG-FEATURESETDOWNLINKPERCC-ID-START + +FeatureSetDownlinkPerCC-Id ::= INTEGER (1..maxPerCC-FeatureSets) + +-- TAG-FEATURESETDOWNLINKPERCC-ID-STOP +-- TAG-FEATURESETEUTRADOWNLINKID-START + +FeatureSetEUTRA-DownlinkId ::= INTEGER (0..maxEUTRA-DL-FeatureSets) + +-- TAG-FEATURESETEUTRADOWNLINKID-STOP +-- TAG-FEATURESETEUTRAUPLINKID-START + +FeatureSetEUTRA-UplinkId ::= INTEGER (0..maxEUTRA-UL-FeatureSets) + +-- TAG-FEATURESETEUTRAUPLINKID-STOP +-- TAG-FEATURESETS-START + +FeatureSets ::= SEQUENCE { + featureSetsDownlink SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink OPTIONAL, + featureSetsDownlinkPerCC SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetDownlinkPerCC OPTIONAL, + featureSetsUplink SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink OPTIONAL, + featureSetsUplinkPerCC SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetUplinkPerCC OPTIONAL, + ..., + [[ + featureSetsDownlink-v1540 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v1540 OPTIONAL, + featureSetsUplink-v1540 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1540 OPTIONAL, + featureSetsUplinkPerCC-v1540 SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetUplinkPerCC-v1540 OPTIONAL + ]], + [[ + featureSetsDownlink-v15a0 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v15a0 OPTIONAL + ]], + [[ + featureSetsDownlink-v1610 SEQUENCE (SIZE (1..maxDownlinkFeatureSets)) OF FeatureSetDownlink-v1610 OPTIONAL, + featureSetsUplink-v1610 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1610 OPTIONAL, + featureSetDownlinkPerCC-v1620 SEQUENCE (SIZE (1..maxPerCC-FeatureSets)) OF FeatureSetDownlinkPerCC-v1620 OPTIONAL + ]], + [[ + featureSetsUplink-v1630 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1630 OPTIONAL + ]], + [[ + featureSetsUplink-v1640 SEQUENCE (SIZE (1..maxUplinkFeatureSets)) OF FeatureSetUplink-v1640 OPTIONAL + ]] +} + +-- TAG-FEATURESETS-STOP +-- TAG-FEATURESETUPLINK-START + +FeatureSetUplink ::= SEQUENCE { + featureSetListPerUplinkCC SEQUENCE (SIZE (1.. maxNrofServingCells)) OF FeatureSetUplinkPerCC-Id, + scalingFactor ENUMERATED {f0p4, f0p75, f0p8} OPTIONAL, + dummy3 ENUMERATED {supported} OPTIONAL, + intraBandFreqSeparationUL FreqSeparationClass OPTIONAL, + searchSpaceSharingCA-UL ENUMERATED {supported} OPTIONAL, + dummy1 DummyI OPTIONAL, + supportedSRS-Resources SRS-Resources OPTIONAL, + twoPUCCH-Group ENUMERATED {supported} OPTIONAL, + dynamicSwitchSUL ENUMERATED {supported} OPTIONAL, + simultaneousTxSUL-NonSUL ENUMERATED {supported} OPTIONAL, + pusch-ProcessingType1-DifferentTB-PerSlot SEQUENCE { + scs-15kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-30kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-60kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL, + scs-120kHz ENUMERATED {upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + dummy2 DummyF OPTIONAL +} + +FeatureSetUplink-v1540 ::= SEQUENCE { + zeroSlotOffsetAperiodicSRS ENUMERATED {supported} OPTIONAL, + pa-PhaseDiscontinuityImpacts ENUMERATED {supported} OPTIONAL, + pusch-SeparationWithGap ENUMERATED {supported} OPTIONAL, + pusch-ProcessingType2 SEQUENCE { + scs-15kHz ProcessingParameters OPTIONAL, + scs-30kHz ProcessingParameters OPTIONAL, + scs-60kHz ProcessingParameters OPTIONAL + } OPTIONAL, + ul-MCS-TableAlt-DynamicIndication ENUMERATED {supported} OPTIONAL +} + +FeatureSetUplink-v1610 ::= SEQUENCE { + -- R1 11-5: PUsCH repetition Type B + pusch-RepetitionTypeB-r16 SEQUENCE { + maxNumberPUSCH-Tx-r16 ENUMERATED {n2, n3, n4, n7, n8, n12}, + hoppingScheme-r16 ENUMERATED {interSlotHopping, interRepetitionHopping, both} + } OPTIONAL, + -- R1 11-7: UL cancelation scheme for self-carrier + ul-CancellationSelfCarrier-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-7a: UL cancelation scheme for cross-carrier + ul-CancellationCrossCarrier-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-5c: The maximum number of SRS resources in one SRS resource set with usage set to 'codebook' for Mode 2 + ul-FullPwrMode2-MaxSRS-ResInSet-r16 ENUMERATED {n1, n2, n4} OPTIONAL, + + -- R1 22-4a/4b/4c/4d: CBG based transmission for UL with unicast PUSCH(s) per slot per CC with UE processing time Capability 1 + cbgPUSCH-ProcessingType1-DifferentTB-PerSlot-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-30kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-60kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-120kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + + -- R1 22-3a/3b/3c/3d: CBG based transmission for UL with unicast PUSCH(s) per slot per CC with UE processing time Capability 2 + cbgPUSCH-ProcessingType2-DifferentTB-PerSlot-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-30kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-60kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL, + scs-120kHz-r16 ENUMERATED {one-pusch, upto2, upto4, upto7} OPTIONAL + } OPTIONAL, + supportedSRS-PosResources-r16 SRS-AllPosResources-r16 OPTIONAL, + intraFreqDAPS-UL-r16 SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL, + intraFreqTwoTAGs-DAPS-r16 ENUMERATED {supported} OPTIONAL, + dummy1 ENUMERATED {supported} OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + dummy3 ENUMERATED {short, long} OPTIONAL + } OPTIONAL, + intraBandFreqSeparationUL-v1620 FreqSeparationClassUL-v1620 OPTIONAL, + + -- R1 11-3: More than one PUCCH for HARQ-ACK transmission within a slot + multiPUCCH-r16 SEQUENCE { + sub-SlotConfig-NCP-r16 ENUMERATED {set1, set2} OPTIONAL, + sub-SlotConfig-ECP-r16 ENUMERATED {set1, set2} OPTIONAL + } OPTIONAL, + -- R1 11-3c: 2 PUCCH of format 0 or 2 for a single 7*2-symbol subslot based HARQ-ACK codebook + twoPUCCH-Type1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-3d: 2 PUCCH of format 0 or 2 for a single 2*7-symbol subslot based HARQ-ACK codebook + twoPUCCH-Type2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-3e: 1 PUCCH format 0 or 2 and 1 PUCCH format 1, 3 or 4 in the same subslot for a single 2*7-symbol HARQ-ACK codebooks + twoPUCCH-Type3-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-3f: 2 PUCCH transmissions in the same subslot for a single 2*7-symbol HARQ-ACK codebooks which are not covered by 11-3d and + -- 11-3e + twoPUCCH-Type4-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-3g: SR/HARQ-ACK multiplexing once per subslot using a PUCCH (or HARQ-ACK piggybacked on a PUSCH) when SR/HARQ-ACK + -- are supposed to be sent with different starting symbols in a subslot + mux-SR-HARQ-ACK-r16 ENUMERATED {supported} OPTIONAL, + dummy1 ENUMERATED {supported} OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + -- R1 11-4c: 2 PUCCH of format 0 or 2 for two HARQ-ACK codebooks with one 7*2-symbol sub-slot based HARQ-ACK codebook + twoPUCCH-Type5-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4d: 2 PUCCH of format 0 or 2 in consecutive symbols for two HARQ-ACK codebooks with one 2*7-symbol sub-slot based HARQ-ACK + -- codebook + twoPUCCH-Type6-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4e: 2 PUCCH of format 0 or 2 for two subslot based HARQ-ACK codebooks + twoPUCCH-Type7-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4f: 1 PUCCH format 0 or 2 and 1 PUCCH format 1, 3 or 4 in the same subslot for HARQ-ACK codebooks with one 2*7-symbol + -- subslot based HARQ-ACK codebook + twoPUCCH-Type8-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4g: 1 PUCCH format 0 or 2 and 1 PUCCH format 1, 3 or 4 in the same subslot for two subslot based HARQ-ACK codebooks + twoPUCCH-Type9-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4h: 2 PUCCH transmissions in the same subslot for two HARQ-ACK codebooks with one 2*7-symbol subslot which are not covered + -- by 11-4c and 11-4e + twoPUCCH-Type10-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-4i: 2 PUCCH transmissions in the same subslot for two subslot based HARQ-ACK codebooks which are not covered by 11-4d and + -- 11-4f + twoPUCCH-Type11-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-1: UL intra-UE multiplexing/prioritization of overlapping channel/signals with two priority levels in physical layer + ul-IntraUE-Mux-r16 SEQUENCE { + pusch-PreparationLowPriority-r16 ENUMERATED {sym0, sym1, sym2}, + pusch-PreparationHighPriority-r16 ENUMERATED {sym0, sym1, sym2} + } OPTIONAL, + -- R1 16-5a: Supported UL full power transmission mode of fullpower + ul-FullPwrMode-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-5d: Processing up to X unicast DCI scheduling for UL per scheduled CC + crossCarrierSchedulingProcessing-DiffSCS-r16 SEQUENCE { + scs-15kHz-120kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-15kHz-60kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-30kHz-120kHz-r16 ENUMERATED {n1,n2,n4} OPTIONAL, + scs-15kHz-30kHz-r16 ENUMERATED {n2} OPTIONAL, + scs-30kHz-60kHz-r16 ENUMERATED {n2} OPTIONAL, + scs-60kHz-120kHz-r16 ENUMERATED {n2} OPTIONAL + } OPTIONAL, + -- R1 16-5b: Supported UL full power transmission mode of fullpowerMode1 + ul-FullPwrMode1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-5c-2: Ports configuration for Mode 2 + ul-FullPwrMode2-SRSConfig-diffNumSRSPorts-r16 ENUMERATED {p1-2, p1-4, p1-2-4} OPTIONAL, + -- R1 16-5c-3: TPMI group for Mode 2 + ul-FullPwrMode2-TPMIGroup-r16 SEQUENCE { + twoPorts-r16 BIT STRING(SIZE(2)) OPTIONAL, + fourPortsNonCoherent-r16 ENUMERATED{g0, g1, g2, g3} OPTIONAL, + fourPortsPartialCoherent-r16 ENUMERATED{g0, g1, g2, g3, g4, g5, g6} OPTIONAL + } OPTIONAL +} + +FeatureSetUplink-v1630 ::= SEQUENCE { + -- R1 22-8: For SRS for CB PUSCH and antenna switching on FR1 with symbol level offset for aperiodic SRS transmission + offsetSRS-CB-PUSCH-Ant-Switch-fr1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-8a: PDCCH monitoring on any span of up to 3 consecutive OFDM symbols of a slot and constrained timeline for SRS for CB + -- PUSCH and antenna switching on FR1 + offsetSRS-CB-PUSCH-PDCCH-MonitorSingleOcc-fr1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-8b: For type 1 CSS with dedicated RRC configuration, type 3 CSS, and UE-SS, monitoring occasion can be any OFDM symbol(s) + -- of a slot for Case 2 and constrained timeline for SRS for CB PUSCH and antenna switching on FR1 + offsetSRS-CB-PUSCH-PDCCH-MonitorAnyOccWithoutGap-fr1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 22-8c: For type 1 CSS with dedicated RRC configuration, type 3 CSS, and UE-SS, monitoring occasion can be any OFDM symbol(s) + -- of a slot for Case 2 with a DCI gap and constrained timeline for SRS for CB PUSCH and antenna switching on FR1 + offsetSRS-CB-PUSCH-PDCCH-MonitorAnyOccWithGap-fr1-r16 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + -- R1 22-9: Cancellation of PUCCH, PUSCH or PRACH with a DCI scheduling a PDSCH or CSI-RS or a DCI format 2_0 for SFI + partialCancellationPUCCH-PUSCH-PRACH-TX-r16 ENUMERATED {supported} OPTIONAL +} + +FeatureSetUplink-v1640 ::= SEQUENCE { + -- R1 11-4: Two HARQ-ACK codebooks with up to one sub-slot based HARQ-ACK codebook (i.e. slot-based + slot-based, or slot-based + + -- sub-slot based) simultaneously constructed for supporting HARQ-ACK codebooks with different priorities at a UE + twoHARQ-ACK-Codebook-type1-r16 SubSlot-Config-r16 OPTIONAL, + -- R1 11-4a: Two sub-slot based HARQ-ACK codebooks simultaneously constructed for supporting HARQ-ACK codebooks with different + -- priorities at a UE + twoHARQ-ACK-Codebook-type2-r16 SubSlot-Config-r16 OPTIONAL, + -- R1 22-8d: All PDCCH monitoring occasion can be any OFDM symbol(s) of a slot for Case 2 with a span gap and constrained timeline + -- for SRS for CB PUSCH and antenna switching on FR1 + offsetSRS-CB-PUSCH-PDCCH-MonitorAnyOccWithSpanGap-fr1-r16 SEQUENCE { + scs-15kHz-r16 ENUMERATED {set1, set2, set3} OPTIONAL, + scs-30kHz-r16 ENUMERATED {set1, set2, set3} OPTIONAL, + scs-60kHz-r16 ENUMERATED {set1, set2, set3} OPTIONAL + } OPTIONAL +} + +SubSlot-Config-r16 ::= SEQUENCE { + sub-SlotConfig-NCP-r16 ENUMERATED {n4,n5,n6,n7} OPTIONAL, + sub-SlotConfig-ECP-r16 ENUMERATED {n4,n5,n6} OPTIONAL +} + +SRS-AllPosResources-r16 ::= SEQUENCE { + srs-PosResources-r16 SRS-PosResources-r16, + srs-PosResourceAP-r16 SRS-PosResourceAP-r16 OPTIONAL, + srs-PosResourceSP-r16 SRS-PosResourceSP-r16 OPTIONAL +} + +SRS-PosResources-r16 ::= SEQUENCE { + maxNumberSRS-PosResourceSetPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n12, n16}, + maxNumberSRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberSRS-ResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14}, + maxNumberPeriodicSRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberPeriodicSRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-PosResourceAP-r16 ::= SEQUENCE { + maxNumberAP-SRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberAP-SRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-PosResourceSP-r16 ::= SEQUENCE { + maxNumberSP-SRS-PosResourcesPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64}, + maxNumberSP-SRS-PosResourcesPerBWP-PerSlot-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n8, n10, n12, n14} +} + +SRS-Resources ::= SEQUENCE { + maxNumberAperiodicSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberAperiodicSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberPeriodicSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberPeriodicSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberSemiPersistentSRS-PerBWP ENUMERATED {n1, n2, n4, n8, n16}, + maxNumberSemiPersistentSRS-PerBWP-PerSlot INTEGER (1..6), + maxNumberSRS-Ports-PerResource ENUMERATED {n1, n2, n4} +} + +DummyF ::= SEQUENCE { + maxNumberPeriodicCSI-ReportPerBWP INTEGER (1..4), + maxNumberAperiodicCSI-ReportPerBWP INTEGER (1..4), + maxNumberSemiPersistentCSI-ReportPerBWP INTEGER (0..4), + simultaneousCSI-ReportsAllCC INTEGER (5..32) +} + +-- TAG-FEATURESETUPLINK-STOP +-- TAG-FEATURESETUPLINKID-START + +FeatureSetUplinkId ::= INTEGER (0..maxUplinkFeatureSets) + +-- TAG-FEATURESETUPLINKID-STOP +-- TAG-FEATURESETUPLINKPERCC-START + +FeatureSetUplinkPerCC ::= SEQUENCE { + supportedSubcarrierSpacingUL SubcarrierSpacing, + supportedBandwidthUL SupportedBandwidth, + channelBW-90mhz ENUMERATED {supported} OPTIONAL, + mimo-CB-PUSCH SEQUENCE { + maxNumberMIMO-LayersCB-PUSCH MIMO-LayersUL OPTIONAL, + maxNumberSRS-ResourcePerSet INTEGER (1..2) + } OPTIONAL, + maxNumberMIMO-LayersNonCB-PUSCH MIMO-LayersUL OPTIONAL, + supportedModulationOrderUL ModulationOrder OPTIONAL +} +FeatureSetUplinkPerCC-v1540 ::= SEQUENCE { + mimo-NonCB-PUSCH SEQUENCE { + maxNumberSRS-ResourcePerSet INTEGER (1..4), + maxNumberSimultaneousSRS-ResourceTx INTEGER (1..4) + } OPTIONAL +} + +-- TAG-FEATURESETUPLINKPERCC-STOP +-- TAG-FEATURESETUPLINKPERCC-ID-START + +FeatureSetUplinkPerCC-Id ::= INTEGER (1..maxPerCC-FeatureSets) + +-- TAG-FEATURESETUPLINKPERCC-ID-STOP +-- TAG-FREQBANDINDICATOREUTRA-START + +FreqBandIndicatorEUTRA ::= INTEGER (1..maxBandsEUTRA) + +-- TAG-FREQBANDINDICATOREUTRA-STOP +-- TAG-FREQBANDLIST-START + +FreqBandList ::= SEQUENCE (SIZE (1..maxBandsMRDC)) OF FreqBandInformation + +FreqBandInformation ::= CHOICE { + bandInformationEUTRA FreqBandInformationEUTRA, + bandInformationNR FreqBandInformationNR +} + +FreqBandInformationEUTRA ::= SEQUENCE { + bandEUTRA FreqBandIndicatorEUTRA, + ca-BandwidthClassDL-EUTRA CA-BandwidthClassEUTRA OPTIONAL, -- Need N + ca-BandwidthClassUL-EUTRA CA-BandwidthClassEUTRA OPTIONAL -- Need N +} + +FreqBandInformationNR ::= SEQUENCE { + bandNR FreqBandIndicatorNR, + maxBandwidthRequestedDL AggregatedBandwidth OPTIONAL, -- Need N + maxBandwidthRequestedUL AggregatedBandwidth OPTIONAL, -- Need N + maxCarriersRequestedDL INTEGER (1..maxNrofServingCells) OPTIONAL, -- Need N + maxCarriersRequestedUL INTEGER (1..maxNrofServingCells) OPTIONAL -- Need N +} + +AggregatedBandwidth ::= ENUMERATED {mhz50, mhz100, mhz150, mhz200, mhz250, mhz300, mhz350, + mhz400, mhz450, mhz500, mhz550, mhz600, mhz650, mhz700, mhz750, mhz800} + +-- TAG-FREQBANDLIST-STOP +-- TAG-FREQSEPARATIONCLASS-START + +FreqSeparationClass ::= ENUMERATED { mhz800, mhz1200, mhz1400, ...} + +FreqSeparationClassDL-v1620 ::= ENUMERATED {mhz1000, mhz1600, mhz1800, mhz2000, mhz2200, mhz2400} + +FreqSeparationClassUL-v1620 ::= ENUMERATED {mhz1000} + +-- TAG-FREQSEPARATIONCLASS-STOP +-- TAG-FREQSEPARATIONCLASSDL-Only-START + +FreqSeparationClassDL-Only-r16 ::= ENUMERATED {mhz200, mhz400, mhz600, mhz800, mhz1000, mhz1200} + +-- TAG-FREQSEPARATIONCLASSDL-Only-STOP +-- TAG-HIGHSPEEDPARAMETERS-START + +HighSpeedParameters-r16 ::= SEQUENCE { + measurementEnhancement-r16 ENUMERATED {supported} OPTIONAL, + demodulationEnhancement-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-HIGHSPEEDPARAMETERS-STOP +-- TAG-IMS-PARAMETERS-START + +IMS-Parameters ::= SEQUENCE { + ims-ParametersCommon IMS-ParametersCommon OPTIONAL, + ims-ParametersFRX-Diff IMS-ParametersFRX-Diff OPTIONAL, + ... +} + +IMS-ParametersCommon ::= SEQUENCE { + voiceOverEUTRA-5GC ENUMERATED {supported} OPTIONAL, + ..., + [[ + voiceOverSCG-BearerEUTRA-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + voiceFallbackIndicationEPS-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +IMS-ParametersFRX-Diff ::= SEQUENCE { + voiceOverNR ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-IMS-PARAMETERS-STOP +-- TAG-INTERRAT-PARAMETERS-START + +InterRAT-Parameters ::= SEQUENCE { + eutra EUTRA-Parameters OPTIONAL, + ..., + [[ + utra-FDD-r16 UTRA-FDD-Parameters-r16 OPTIONAL + ]] + +} + +EUTRA-Parameters ::= SEQUENCE { + supportedBandListEUTRA SEQUENCE (SIZE (1..maxBandsEUTRA)) OF FreqBandIndicatorEUTRA, + eutra-ParametersCommon EUTRA-ParametersCommon OPTIONAL, + eutra-ParametersXDD-Diff EUTRA-ParametersXDD-Diff OPTIONAL, + ... +} + +EUTRA-ParametersCommon ::= SEQUENCE { + mfbi-EUTRA ENUMERATED {supported} OPTIONAL, + modifiedMPR-BehaviorEUTRA BIT STRING (SIZE (32)) OPTIONAL, + multiNS-Pmax-EUTRA ENUMERATED {supported} OPTIONAL, + rs-SINR-MeasEUTRA ENUMERATED {supported} OPTIONAL, + ..., + [[ + ne-DC ENUMERATED {supported} OPTIONAL + ]], + [[ + nr-HO-ToEN-DC-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +EUTRA-ParametersXDD-Diff ::= SEQUENCE { + rsrqMeasWidebandEUTRA ENUMERATED {supported} OPTIONAL, + ... +} + +UTRA-FDD-Parameters-r16 ::= SEQUENCE { + supportedBandListUTRA-FDD-r16 SEQUENCE (SIZE (1..maxBandsUTRA-FDD-r16)) OF SupportedBandUTRA-FDD-r16, + ... +} + +SupportedBandUTRA-FDD-r16 ::= ENUMERATED { + bandI, bandII, bandIII, bandIV, bandV, bandVI, + bandVII, bandVIII, bandIX, bandX, bandXI, + bandXII, bandXIII, bandXIV, bandXV, bandXVI, + bandXVII, bandXVIII, bandXIX, bandXX, + bandXXI, bandXXII, bandXXIII, bandXXIV, + bandXXV, bandXXVI, bandXXVII, bandXXVIII, + bandXXIX, bandXXX, bandXXXI, bandXXXII} + +-- TAG-INTERRAT-PARAMETERS-STOP +-- TAG-MAC-PARAMETERS-START + +MAC-Parameters ::= SEQUENCE { + mac-ParametersCommon MAC-ParametersCommon OPTIONAL, + mac-ParametersXDD-Diff MAC-ParametersXDD-Diff OPTIONAL +} + +MAC-Parameters-v1610 ::= SEQUENCE { + mac-ParametersFRX-Diff-r16 MAC-ParametersFRX-Diff-r16 OPTIONAL +} + +MAC-ParametersCommon ::= SEQUENCE { + lcp-Restriction ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + lch-ToSCellRestriction ENUMERATED {supported} OPTIONAL, + ..., + [[ + recommendedBitRate ENUMERATED {supported} OPTIONAL, + recommendedBitRateQuery ENUMERATED {supported} OPTIONAL + ]], + [[ + recommendedBitRateMultiplier-r16 ENUMERATED {supported} OPTIONAL, + preEmptiveBSR-r16 ENUMERATED {supported} OPTIONAL, + autonomousTransmission-r16 ENUMERATED {supported} OPTIONAL, + lch-PriorityBasedPrioritization-r16 ENUMERATED {supported} OPTIONAL, + lch-ToConfiguredGrantMapping-r16 ENUMERATED {supported} OPTIONAL, + lch-ToGrantPriorityRestriction-r16 ENUMERATED {supported} OPTIONAL, + singlePHR-P-r16 ENUMERATED {supported} OPTIONAL, + ul-LBT-FailureDetectionRecovery-r16 ENUMERATED {supported} OPTIONAL, + -- R4 8-1: MPE + tdd-MPE-P-MPR-Reporting-r16 ENUMERATED {supported} OPTIONAL, + lcid-ExtensionIAB-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + spCell-BFR-CBRA-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +MAC-ParametersFRX-Diff-r16 ::= SEQUENCE { + directMCG-SCellActivation-r16 ENUMERATED {supported} OPTIONAL, + directMCG-SCellActivationResume-r16 ENUMERATED {supported} OPTIONAL, + directSCG-SCellActivation-r16 ENUMERATED {supported} OPTIONAL, + directSCG-SCellActivationResume-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-1: DRX Adaptation + drx-Adaptation-r16 SEQUENCE { + non-SharedSpectrumChAccess-r16 MinTimeGap-r16 OPTIONAL, + sharedSpectrumChAccess-r16 MinTimeGap-r16 OPTIONAL + } OPTIONAL, + ... +} + +MAC-ParametersXDD-Diff ::= SEQUENCE { + skipUplinkTxDynamic ENUMERATED {supported} OPTIONAL, + logicalChannelSR-DelayTimer ENUMERATED {supported} OPTIONAL, + longDRX-Cycle ENUMERATED {supported} OPTIONAL, + shortDRX-Cycle ENUMERATED {supported} OPTIONAL, + multipleSR-Configurations ENUMERATED {supported} OPTIONAL, + multipleConfiguredGrants ENUMERATED {supported} OPTIONAL, + ..., + [[ + secondaryDRX-Group-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + enhancedSkipUplinkTxDynamic-r16 ENUMERATED {supported} OPTIONAL, + enhancedSkipUplinkTxConfigured-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +MinTimeGap-r16 ::= SEQUENCE { + scs-15kHz-r16 ENUMERATED {sl1, sl3} OPTIONAL, + scs-30kHz-r16 ENUMERATED {sl1, sl6} OPTIONAL, + scs-60kHz-r16 ENUMERATED {sl1, sl12} OPTIONAL, + scs-120kHz-r16 ENUMERATED {sl2, sl24} OPTIONAL +} + +-- TAG-MAC-PARAMETERS-STOP +-- TAG-MEASANDMOBPARAMETERS-START + +MeasAndMobParameters ::= SEQUENCE { + measAndMobParametersCommon MeasAndMobParametersCommon OPTIONAL, + measAndMobParametersXDD-Diff MeasAndMobParametersXDD-Diff OPTIONAL, + measAndMobParametersFRX-Diff MeasAndMobParametersFRX-Diff OPTIONAL +} + +MeasAndMobParametersCommon ::= SEQUENCE { + supportedGapPattern BIT STRING (SIZE (22)) OPTIONAL, + ssb-RLM ENUMERATED {supported} OPTIONAL, + ssb-AndCSI-RS-RLM ENUMERATED {supported} OPTIONAL, + ..., + [[ + eventB-MeasAndReport ENUMERATED {supported} OPTIONAL, + handoverFDD-TDD ENUMERATED {supported} OPTIONAL, + eutra-CGI-Reporting ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting ENUMERATED {supported} OPTIONAL + ]], + [[ + independentGapConfig ENUMERATED {supported} OPTIONAL, + periodicEUTRA-MeasAndReport ENUMERATED {supported} OPTIONAL, + handoverFR1-FR2 ENUMERATED {supported} OPTIONAL, + maxNumberCSI-RS-RRM-RS-SINR ENUMERATED {n4, n8, n16, n32, n64, n96} OPTIONAL + ]], + [[ + nr-CGI-Reporting-ENDC ENUMERATED {supported} OPTIONAL + ]], + [[ + eutra-CGI-Reporting-NEDC ENUMERATED {supported} OPTIONAL, + eutra-CGI-Reporting-NRDC ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NEDC ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NRDC ENUMERATED {supported} OPTIONAL + ]], + [[ + reportAddNeighMeasForPeriodic-r16 ENUMERATED {supported} OPTIONAL, + condHandoverParametersCommon-r16 SEQUENCE { + condHandoverFDD-TDD-r16 ENUMERATED {supported} OPTIONAL, + condHandoverFR1-FR2-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + nr-NeedForGap-Reporting-r16 ENUMERATED {supported} OPTIONAL, + supportedGapPattern-NRonly-r16 BIT STRING (SIZE (10)) OPTIONAL, + supportedGapPattern-NRonly-NEDC-r16 ENUMERATED {supported} OPTIONAL, + maxNumberCLI-RSSI-r16 ENUMERATED {n8, n16, n32, n64} OPTIONAL, + maxNumberCLI-SRS-RSRP-r16 ENUMERATED {n4, n8, n16, n32} OPTIONAL, + maxNumberPerSlotCLI-SRS-RSRP-r16 ENUMERATED {n2, n4, n8} OPTIONAL, + mfbi-IAB-r16 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + nr-CGI-Reporting-NPN-r16 ENUMERATED {supported} OPTIONAL, + idleInactiveEUTRA-MeasReport-r16 ENUMERATED {supported} OPTIONAL, + idleInactive-ValidityArea-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGaps-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGaps-NEDC-r16 ENUMERATED {supported} OPTIONAL, + eutra-AutonomousGaps-NRDC-r16 ENUMERATED {supported} OPTIONAL, + pcellT312-r16 ENUMERATED {supported} OPTIONAL, + supportedGapPattern-r16 BIT STRING (SIZE (2)) OPTIONAL + ]] +} + +MeasAndMobParametersXDD-Diff ::= SEQUENCE { + intraAndInterF-MeasAndReport ENUMERATED {supported} OPTIONAL, + eventA-MeasAndReport ENUMERATED {supported} OPTIONAL, + ..., + [[ + handoverInterF ENUMERATED {supported} OPTIONAL, + handoverLTE-EPC ENUMERATED {supported} OPTIONAL, + handoverLTE-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + sftd-MeasNR-Neigh ENUMERATED {supported} OPTIONAL, + sftd-MeasNR-Neigh-DRX ENUMERATED {supported} OPTIONAL + ]], + [[ + dummy ENUMERATED {supported} OPTIONAL + ]] +} + +MeasAndMobParametersFRX-Diff ::= SEQUENCE { + ss-SINR-Meas ENUMERATED {supported} OPTIONAL, + csi-RSRP-AndRSRQ-MeasWithSSB ENUMERATED {supported} OPTIONAL, + csi-RSRP-AndRSRQ-MeasWithoutSSB ENUMERATED {supported} OPTIONAL, + csi-SINR-Meas ENUMERATED {supported} OPTIONAL, + csi-RS-RLM ENUMERATED {supported} OPTIONAL, + ..., + [[ + handoverInterF ENUMERATED {supported} OPTIONAL, + handoverLTE-EPC ENUMERATED {supported} OPTIONAL, + handoverLTE-5GC ENUMERATED {supported} OPTIONAL + ]], + [[ + maxNumberResource-CSI-RS-RLM ENUMERATED {n2, n4, n6, n8} OPTIONAL + ]], + [[ + simultaneousRxDataSSB-DiffNumerology ENUMERATED {supported} OPTIONAL + ]], + [[ + nr-AutonomousGaps-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-ENDC-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-NEDC-r16 ENUMERATED {supported} OPTIONAL, + nr-AutonomousGaps-NRDC-r16 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + cli-RSSI-Meas-r16 ENUMERATED {supported} OPTIONAL, + cli-SRS-RSRP-Meas-r16 ENUMERATED {supported} OPTIONAL, + interFrequencyMeas-NoGap-r16 ENUMERATED {supported} OPTIONAL, + simultaneousRxDataSSB-DiffNumerology-Inter-r16 ENUMERATED {supported} OPTIONAL, + idleInactiveNR-MeasReport-r16 ENUMERATED {supported} OPTIONAL, + -- R4 6-2: Support of beam level Early Measurement Reporting + idleInactiveNR-MeasBeamReport-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + increasedNumberofCSIRSPerMO-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-MEASANDMOBPARAMETERS-STOP +-- TAG-MEASANDMOBPARAMETERSMRDC-START + +MeasAndMobParametersMRDC ::= SEQUENCE { + measAndMobParametersMRDC-Common MeasAndMobParametersMRDC-Common OPTIONAL, + measAndMobParametersMRDC-XDD-Diff MeasAndMobParametersMRDC-XDD-Diff OPTIONAL, + measAndMobParametersMRDC-FRX-Diff MeasAndMobParametersMRDC-FRX-Diff OPTIONAL +} + +MeasAndMobParametersMRDC-v1560 ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff-v1560 MeasAndMobParametersMRDC-XDD-Diff-v1560 OPTIONAL +} + +MeasAndMobParametersMRDC-v1610 ::= SEQUENCE { + measAndMobParametersMRDC-Common-v1610 MeasAndMobParametersMRDC-Common-v1610 OPTIONAL, + interNR-MeasEUTRA-IAB-r16 ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-Common ::= SEQUENCE { + independentGapConfig ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-Common-v1610 ::= SEQUENCE { + condPSCellChangeParametersCommon-r16 SEQUENCE { + condPSCellChangeFDD-TDD-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChangeFR1-FR2-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + pscellT312-r16 ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-XDD-Diff ::= SEQUENCE { + sftd-MeasPSCell ENUMERATED {supported} OPTIONAL, + sftd-MeasNR-Cell ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-XDD-Diff-v1560 ::= SEQUENCE { + sftd-MeasPSCell-NEDC ENUMERATED {supported} OPTIONAL +} + +MeasAndMobParametersMRDC-FRX-Diff ::= SEQUENCE { + simultaneousRxDataSSB-DiffNumerology ENUMERATED {supported} OPTIONAL +} + +-- TAG-MEASANDMOBPARAMETERSMRDC-STOP +-- TAG-MIMO-LAYERS-START + +MIMO-LayersDL ::= ENUMERATED {twoLayers, fourLayers, eightLayers} + +MIMO-LayersUL ::= ENUMERATED {oneLayer, twoLayers, fourLayers} + +-- TAG-MIMO-LAYERS-STOP +-- TAG-MIMO-PARAMETERSPERBAND-START + +MIMO-ParametersPerBand ::= SEQUENCE { + tci-StatePDSCH SEQUENCE { + maxNumberConfiguredTCIstatesPerCC ENUMERATED {n4, n8, n16, n32, n64, n128} OPTIONAL, + maxNumberActiveTCI-PerBWP ENUMERATED {n1, n2, n4, n8} OPTIONAL + } OPTIONAL, + additionalActiveTCI-StatePDCCH ENUMERATED {supported} OPTIONAL, + pusch-TransCoherence ENUMERATED {nonCoherent, partialCoherent, fullCoherent} OPTIONAL, + beamCorrespondenceWithoutUL-BeamSweeping ENUMERATED {supported} OPTIONAL, + periodicBeamReport ENUMERATED {supported} OPTIONAL, + aperiodicBeamReport ENUMERATED {supported} OPTIONAL, + sp-BeamReportPUCCH ENUMERATED {supported} OPTIONAL, + sp-BeamReportPUSCH ENUMERATED {supported} OPTIONAL, + dummy1 DummyG OPTIONAL, + maxNumberRxBeam INTEGER (2..8) OPTIONAL, + maxNumberRxTxBeamSwitchDL SEQUENCE { + scs-15kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-30kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-60kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-120kHz ENUMERATED {n4, n7, n14} OPTIONAL, + scs-240kHz ENUMERATED {n4, n7, n14} OPTIONAL + } OPTIONAL, + maxNumberNonGroupBeamReporting ENUMERATED {n1, n2, n4} OPTIONAL, + groupBeamReporting ENUMERATED {supported} OPTIONAL, + uplinkBeamManagement SEQUENCE { + maxNumberSRS-ResourcePerSet-BM ENUMERATED {n2, n4, n8, n16}, + maxNumberSRS-ResourceSet INTEGER (1..8) + } OPTIONAL, + maxNumberCSI-RS-BFD INTEGER (1..64) OPTIONAL, + maxNumberSSB-BFD INTEGER (1..64) OPTIONAL, + maxNumberCSI-RS-SSB-CBD INTEGER (1..256) OPTIONAL, + dummy2 ENUMERATED {supported} OPTIONAL, + twoPortsPTRS-UL ENUMERATED {supported} OPTIONAL, + dummy5 SRS-Resources OPTIONAL, + dummy3 INTEGER (1..4) OPTIONAL, + beamReportTiming SEQUENCE { + scs-15kHz ENUMERATED {sym2, sym4, sym8} OPTIONAL, + scs-30kHz ENUMERATED {sym4, sym8, sym14, sym28} OPTIONAL, + scs-60kHz ENUMERATED {sym8, sym14, sym28} OPTIONAL, + scs-120kHz ENUMERATED {sym14, sym28, sym56} OPTIONAL + } OPTIONAL, + ptrs-DensityRecommendationSetDL SEQUENCE { + scs-15kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-30kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-60kHz PTRS-DensityRecommendationDL OPTIONAL, + scs-120kHz PTRS-DensityRecommendationDL OPTIONAL + } OPTIONAL, + ptrs-DensityRecommendationSetUL SEQUENCE { + scs-15kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-30kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-60kHz PTRS-DensityRecommendationUL OPTIONAL, + scs-120kHz PTRS-DensityRecommendationUL OPTIONAL + } OPTIONAL, + dummy4 DummyH OPTIONAL, + aperiodicTRS ENUMERATED {supported} OPTIONAL, + ..., + [[ + dummy6 ENUMERATED {true} OPTIONAL, + beamManagementSSB-CSI-RS BeamManagementSSB-CSI-RS OPTIONAL, + beamSwitchTiming SEQUENCE { + scs-60kHz ENUMERATED {sym14, sym28, sym48, sym224, sym336} OPTIONAL, + scs-120kHz ENUMERATED {sym14, sym28, sym48, sym224, sym336} OPTIONAL + } OPTIONAL, + codebookParameters CodebookParameters OPTIONAL, + csi-RS-IM-ReceptionForFeedback CSI-RS-IM-ReceptionForFeedback OPTIONAL, + csi-RS-ProcFrameworkForSRS CSI-RS-ProcFrameworkForSRS OPTIONAL, + csi-ReportFramework CSI-ReportFramework OPTIONAL, + csi-RS-ForTracking CSI-RS-ForTracking OPTIONAL, + srs-AssocCSI-RS SEQUENCE (SIZE (1.. maxNrofCSI-RS-Resources)) OF SupportedCSI-RS-Resource OPTIONAL, + spatialRelations SpatialRelations OPTIONAL + ]], + [[ + -- R1 16-2b-0: Support of default QCL assumption with two TCI states + defaultQCL-TwoTCI-r16 ENUMERATED {supported} OPTIONAL, + codebookParametersPerBand-r16 CodebookParameters-v1610 OPTIONAL, + -- R1 16-1b-3: Support of PUCCH resource groups per BWP for simultaneous spatial relation update + simul-SpatialRelationUpdatePUCCHResGroup-r16 ENUMERATED {supported} OPTIONAL, + + -- R1 16-1f: Maximum number of SCells configured for SCell beam failure recovery simultaneously + maxNumberSCellBFR-r16 ENUMERATED {n1,n2,n4,n8} OPTIONAL, + + -- R1 16-2c: Supports simultaneous reception with different Type-D for FR2 only + simultaneousReceptionDiffTypeD-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1a-1: SSB/CSI-RS for L1-SINR measurement + ssb-csirs-SINR-measurement-r16 SEQUENCE { + maxNumberSSB-CSIRS-OneTx-CMR-r16 ENUMERATED {n8, n16, n32, n64}, + maxNumberCSI-IM-NZP-IMR-res-r16 ENUMERATED {n8, n16, n32, n64}, + maxNumberCSIRS-2Tx-res-r16 ENUMERATED {n0, n4, n8, n16, n32, n64}, + maxNumberSSB-CSIRS-res-r16 ENUMERATED {n8, n16, n32, n64, n128}, + maxNumberCSI-IM-NZP-IMR-res-mem-r16 ENUMERATED {n8, n16, n32, n64, n128}, + supportedCSI-RS-Density-CMR-r16 ENUMERATED {one, three, oneAndThree}, + maxNumberAperiodicCSI-RS-Res-r16 ENUMERATED {n2, n4, n8, n16, n32, n64}, + supportedSINR-meas-r16 ENUMERATED {ssbWithCSI-IM, ssbWithNZP-IMR, csirsWithNZP-IMR, csi-RSWithoutIMR} OPTIONAL + } OPTIONAL, + -- R1 16-1a-2: Non-group based L1-SINR reporting + nonGroupSINR-reporting-r16 ENUMERATED {n1, n2, n4} OPTIONAL, + -- R1 16-1a-3: Non-group based L1-SINR reporting + groupSINR-reporting-r16 ENUMERATED {supported} OPTIONAL, + + multiDCI-multiTRP-Parameters-r16 SEQUENCE { + -- R1 16-2a-0: Overlapping PDSCHs in time and fully overlapping in frequency and time + overlapPDSCHsFullyFreqTime-r16 INTEGER (1..2) OPTIONAL, + -- R1 16-2a-1: Overlapping PDSCHs in time and partially overlapping in frequency and time + overlapPDSCHsInTimePartiallyFreq-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2a-2: Out of order operation for DL + outOfOrderOperationDL-r16 SEQUENCE { + supportPDCCH-ToPDSCH-r16 ENUMERATED {supported} OPTIONAL, + supportPDSCH-ToHARQ-ACK-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- R1 16-2a-3: Out of order operation for UL + outOfOrderOperationUL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2a-5: Separate CRS rate matching + separateCRS-RateMatching-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2a-6: Default QCL enhancement for multi-DCI based multi-TRP + defaultQCL-PerCORESETPoolIndex-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2a-7: Maximum number of activated TCI states + maxNumberActivatedTCI-States-r16 SEQUENCE { + maxNumberPerCORESET-Pool-r16 ENUMERATED {n1, n2, n4, n8}, + maxTotalNumberAcrossCORESET-Pool-r16 ENUMERATED {n2, n4, n8, n16} + } OPTIONAL + } OPTIONAL, + singleDCI-SDM-scheme-Parameters-r16 SEQUENCE { + -- R1 16-2b-1b: Single-DCI based SDM scheme - Support of new DMRS port entry + supportNewDMRS-Port-r16 ENUMERATED {n0, n2, n3} OPTIONAL, + -- R1 16-2b-1a: Support of s-port DL PTRS + supportTwoPortDL-PTRS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- R1 16-2b-2: Support of single-DCI based FDMSchemeA + supportFDM-SchemeA-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2b-3a: Single-DCI based FDMSchemeB CW soft combining + supportCodeWordSoftCombining-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-2b-4: Single-DCI based TDMSchemeA + supportTDM-SchemeA-r16 ENUMERATED {kb3, kb5, kb10, kb20, noRestriction} OPTIONAL, + -- R1 16-2b-5: Single-DCI based inter-slot TDM + supportInter-slotTDM-r16 SEQUENCE { + supportRepNumPDSCH-TDRA-r16 ENUMERATED {n2, n3, n4, n5, n6, n7, n8, n16}, + maxTBS-Size-r16 ENUMERATED {kb3, kb5, kb10, kb20, noRestriction}, + maxNumberTCI-states-r16 INTEGER (1..2) + } OPTIONAL, + -- R1 16-4: Low PAPR DMRS for PDSCH + lowPAPR-DMRS-PDSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-6a: Low PAPR DMRS for PUSCH without transform precoding + lowPAPR-DMRS-PUSCHwithoutPrecoding-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-6b: Low PAPR DMRS for PUCCH + lowPAPR-DMRS-PUCCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-6c: Low PAPR DMRS for PUSCH with transform precoding & pi/2 BPSK + lowPAPR-DMRS-PUSCHwithPrecoding-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-7: Extension of the maximum number of configured aperiodic CSI report settings + csi-ReportFrameworkExt-r16 CSI-ReportFrameworkExt-r16 OPTIONAL, + -- R1 16-3a, 16-3a-1, 16-3b, 16-3b-1, 16-8: Individual new codebook types + codebookParametersAddition-r16 CodebookParametersAddition-r16 OPTIONAL, + -- R1 16-8: Mixed codebook types + codebookComboParametersAddition-r16 CodebookComboParametersAddition-r16 OPTIONAL, + -- R4 8-2: SSB based beam correspondence + beamCorrespondenceSSB-based-r16 ENUMERATED {supported} OPTIONAL, + -- R4 8-3: CSI-RS based beam correspondence + beamCorrespondenceCSI-RS-based-r16 ENUMERATED {supported} OPTIONAL, + beamSwitchTiming-r16 SEQUENCE { + scs-60kHz-r16 ENUMERATED {sym224, sym336} OPTIONAL, + scs-120kHz-r16 ENUMERATED {sym224, sym336} OPTIONAL + } OPTIONAL + ]], + [[ + -- R1 16-1a-4: Semi-persistent L1-SINR report on PUCCH + semi-PersistentL1-SINR-Report-PUCCH-r16 SEQUENCE { + supportReportFormat1-2OFDM-syms-r16 ENUMERATED {supported} OPTIONAL, + supportReportFormat4-14OFDM-syms-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- R1 16-1a-5: Semi-persistent L1-SINR report on PUSCH + semi-PersistentL1-SINR-Report-PUSCH-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R1 16-1h: Support of 64 configured PUCCH spatial relations + spatialRelations-v1640 SEQUENCE { + maxNumberConfiguredSpatialRelations-v1640 ENUMERATED {n96, n128, n160, n192, n224, n256, n288, n320} + } OPTIONAL, + -- R1 16-1i: Support of 64 configured candidate beam RSs for BFR + support64CandidateBeamRS-BFR-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +DummyG ::= SEQUENCE { + maxNumberSSB-CSI-RS-ResourceOneTx ENUMERATED {n8, n16, n32, n64}, + maxNumberSSB-CSI-RS-ResourceTwoTx ENUMERATED {n0, n4, n8, n16, n32, n64}, + supportedCSI-RS-Density ENUMERATED {one, three, oneAndThree} +} + +BeamManagementSSB-CSI-RS ::= SEQUENCE { + maxNumberSSB-CSI-RS-ResourceOneTx ENUMERATED {n0, n8, n16, n32, n64}, + maxNumberCSI-RS-Resource ENUMERATED {n0, n4, n8, n16, n32, n64}, + maxNumberCSI-RS-ResourceTwoTx ENUMERATED {n0, n4, n8, n16, n32, n64}, + supportedCSI-RS-Density ENUMERATED {one, three, oneAndThree} OPTIONAL, + maxNumberAperiodicCSI-RS-Resource ENUMERATED {n0, n1, n4, n8, n16, n32, n64} +} + +DummyH ::= SEQUENCE { + burstLength INTEGER (1..2), + maxSimultaneousResourceSetsPerCC INTEGER (1..8), + maxConfiguredResourceSetsPerCC INTEGER (1..64), + maxConfiguredResourceSetsAllCC INTEGER (1..128) +} + +CSI-RS-ForTracking ::= SEQUENCE { + maxBurstLength INTEGER (1..2), + maxSimultaneousResourceSetsPerCC INTEGER (1..8), + maxConfiguredResourceSetsPerCC INTEGER (1..64), + maxConfiguredResourceSetsAllCC INTEGER (1..256) +} + +CSI-RS-IM-ReceptionForFeedback ::= SEQUENCE { + maxConfigNumberNZP-CSI-RS-PerCC INTEGER (1..64), + maxConfigNumberPortsAcrossNZP-CSI-RS-PerCC INTEGER (2..256), + maxConfigNumberCSI-IM-PerCC ENUMERATED {n1, n2, n4, n8, n16, n32}, + maxNumberSimultaneousNZP-CSI-RS-PerCC INTEGER (1..64), + totalNumberPortsSimultaneousNZP-CSI-RS-PerCC INTEGER (2..256) +} + +CSI-RS-ProcFrameworkForSRS ::= SEQUENCE { + maxNumberPeriodicSRS-AssocCSI-RS-PerBWP INTEGER (1..4), + maxNumberAperiodicSRS-AssocCSI-RS-PerBWP INTEGER (1..4), + maxNumberSP-SRS-AssocCSI-RS-PerBWP INTEGER (0..4), + simultaneousSRS-AssocCSI-RS-PerCC INTEGER (1..8) +} + +CSI-ReportFramework ::= SEQUENCE { + maxNumberPeriodicCSI-PerBWP-ForCSI-Report INTEGER (1..4), + maxNumberAperiodicCSI-PerBWP-ForCSI-Report INTEGER (1..4), + maxNumberSemiPersistentCSI-PerBWP-ForCSI-Report INTEGER (0..4), + maxNumberPeriodicCSI-PerBWP-ForBeamReport INTEGER (1..4), + maxNumberAperiodicCSI-PerBWP-ForBeamReport INTEGER (1..4), + maxNumberAperiodicCSI-triggeringStatePerCC ENUMERATED {n3, n7, n15, n31, n63, n128}, + maxNumberSemiPersistentCSI-PerBWP-ForBeamReport INTEGER (0..4), + simultaneousCSI-ReportsPerCC INTEGER (1..8) +} + +CSI-ReportFrameworkExt-r16 ::= SEQUENCE { + maxNumberAperiodicCSI-PerBWP-ForCSI-ReportExt-r16 INTEGER (5..8) +} + +PTRS-DensityRecommendationDL ::= SEQUENCE { + frequencyDensity1 INTEGER (1..276), + frequencyDensity2 INTEGER (1..276), + timeDensity1 INTEGER (0..29), + timeDensity2 INTEGER (0..29), + timeDensity3 INTEGER (0..29) +} + +PTRS-DensityRecommendationUL ::= SEQUENCE { + frequencyDensity1 INTEGER (1..276), + frequencyDensity2 INTEGER (1..276), + timeDensity1 INTEGER (0..29), + timeDensity2 INTEGER (0..29), + timeDensity3 INTEGER (0..29), + sampleDensity1 INTEGER (1..276), + sampleDensity2 INTEGER (1..276), + sampleDensity3 INTEGER (1..276), + sampleDensity4 INTEGER (1..276), + sampleDensity5 INTEGER (1..276) +} + +SpatialRelations ::= SEQUENCE { + maxNumberConfiguredSpatialRelations ENUMERATED {n4, n8, n16, n32, n64, n96}, + maxNumberActiveSpatialRelations ENUMERATED {n1, n2, n4, n8, n14}, + additionalActiveSpatialRelationPUCCH ENUMERATED {supported} OPTIONAL, + maxNumberDL-RS-QCL-TypeD ENUMERATED {n1, n2, n4, n8, n14} +} + +DummyI ::= SEQUENCE { + supportedSRS-TxPortSwitch ENUMERATED {t1r2, t1r4, t2r4, t1r4-t2r4, tr-equal}, + txSwitchImpactToRx ENUMERATED {true} OPTIONAL +} + +-- TAG-MIMO-PARAMETERSPERBAND-STOP +-- TAG-MODULATIONORDER-START + +ModulationOrder ::= ENUMERATED {bpsk-halfpi, bpsk, qpsk, qam16, qam64, qam256} + +-- TAG-MODULATIONORDER-STOP +-- TAG-MRDC-PARAMETERS-START + +MRDC-Parameters ::= SEQUENCE { + singleUL-Transmission ENUMERATED {supported} OPTIONAL, + dynamicPowerSharingENDC ENUMERATED {supported} OPTIONAL, + tdm-Pattern ENUMERATED {supported} OPTIONAL, + ul-SharingEUTRA-NR ENUMERATED {tdm, fdm, both} OPTIONAL, + ul-SwitchingTimeEUTRA-NR ENUMERATED {type1, type2} OPTIONAL, + simultaneousRxTxInterBandENDC ENUMERATED {supported} OPTIONAL, + asyncIntraBandENDC ENUMERATED {supported} OPTIONAL, + ..., + [[ + dualPA-Architecture ENUMERATED {supported} OPTIONAL, + intraBandENDC-Support ENUMERATED {non-contiguous, both} OPTIONAL, + ul-TimingAlignmentEUTRA-NR ENUMERATED {required} OPTIONAL + ]] +} + +MRDC-Parameters-v1580 ::= SEQUENCE { + dynamicPowerSharingNEDC ENUMERATED {supported} OPTIONAL +} + +MRDC-Parameters-v1590 ::= SEQUENCE { + interBandContiguousMRDC ENUMERATED {supported} OPTIONAL +} + +MRDC-Parameters-v1620 ::= SEQUENCE { + maxUplinkDutyCycle-interBandENDC-TDD-PC2-r16 SEQUENCE{ + eutra-TDD-Config0-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config1-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config2-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config3-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config4-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config5-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + eutra-TDD-Config6-r16 ENUMERATED {n20, n40, n50, n60, n70, n80, n90, n100} OPTIONAL + } OPTIONAL, + -- R1 18-2 Single UL TX operation for TDD PCell in EN-DC + tdm-restrictionTDD-endc-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-2a Single UL TX operation for FDD PCell in EN-DC + tdm-restrictionFDD-endc-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-2b Support of HARQ-offset for SUO case1 in EN-DC with LTE TDD PCell for type 1 UE + singleUL-HARQ-offsetTDD-PCell-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-3 Dual Tx transmission for EN-DC with FDD PCell(TDM pattern for dual Tx UE) + tdm-restrictionDualTX-FDD-endc-r16 ENUMERATED {supported} OPTIONAL +} + +MRDC-Parameters-v1630 ::= SEQUENCE { + -- R4 2-20 Maximum uplink duty cycle for FDD+TDD EN-DC power class 2 + maxUplinkDutyCycle-interBandENDC-FDD-TDD-PC2-r16 SEQUENCE { + maxUplinkDutyCycle-FDD-TDD-EN-DC1-r16 ENUMERATED {n30, n40, n50, n60, n70, n80, n90, n100} OPTIONAL, + maxUplinkDutyCycle-FDD-TDD-EN-DC2-r16 ENUMERATED {n30, n40, n50, n60, n70, n80, n90, n100} OPTIONAL + } OPTIONAL, + + -- R4 2-19 FDD-FDD or TDD-TDD inter-band MR-DC with overlapping or partially overlapping DL spectrum + interBandMRDC-WithOverlapDL-Bands-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-MRDC-PARAMETERS-STOP +-- TAG-NRDC-PARAMETERS-START + +NRDC-Parameters ::= SEQUENCE { + measAndMobParametersNRDC MeasAndMobParametersMRDC OPTIONAL, + generalParametersNRDC GeneralParametersMRDC-XDD-Diff OPTIONAL, + fdd-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-NRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + dummy2 OCTET STRING OPTIONAL, + dummy SEQUENCE {} OPTIONAL +} + +NRDC-Parameters-v1570 ::= SEQUENCE { + sfn-SyncNRDC ENUMERATED {supported} OPTIONAL +} + +NRDC-Parameters-v15c0 ::= SEQUENCE { + pdcp-DuplicationSplitSRB ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationSplitDRB ENUMERATED {supported} OPTIONAL +} + +NRDC-Parameters-v1610 ::= SEQUENCE { + measAndMobParametersNRDC-v1610 MeasAndMobParametersMRDC-v1610 OPTIONAL +} + + +-- TAG-NRDC-PARAMETERS-STOP +-- TAG-OLPC-SRS-POS-START + +OLPC-SRS-Pos-r16 ::= SEQUENCE { + olpc-SRS-PosBasedOnPRS-Serving-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-PosBasedOnSSB-Neigh-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-PosBasedOnPRS-Neigh-r16 ENUMERATED {supported} OPTIONAL, + maxNumberPathLossEstimatePerServing-r16 ENUMERATED {n1, n4, n8, n16} OPTIONAL +} + +--TAG-OLPC-SRS-POS-STOP +-- TAG-PDCP-PARAMETERS-START + +PDCP-Parameters ::= SEQUENCE { + supportedROHC-Profiles SEQUENCE { + profile0x0000 BOOLEAN, + profile0x0001 BOOLEAN, + profile0x0002 BOOLEAN, + profile0x0003 BOOLEAN, + profile0x0004 BOOLEAN, + profile0x0006 BOOLEAN, + profile0x0101 BOOLEAN, + profile0x0102 BOOLEAN, + profile0x0103 BOOLEAN, + profile0x0104 BOOLEAN + }, + maxNumberROHC-ContextSessions ENUMERATED {cs2, cs4, cs8, cs12, cs16, cs24, cs32, cs48, cs64, + cs128, cs256, cs512, cs1024, cs16384, spare2, spare1}, + uplinkOnlyROHC-Profiles ENUMERATED {supported} OPTIONAL, + continueROHC-Context ENUMERATED {supported} OPTIONAL, + outOfOrderDelivery ENUMERATED {supported} OPTIONAL, + shortSN ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationSRB ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationMCG-OrSCG-DRB ENUMERATED {supported} OPTIONAL, + ..., + [[ + drb-IAB-r16 ENUMERATED {supported} OPTIONAL, + non-DRB-IAB-r16 ENUMERATED {supported} OPTIONAL, + extendedDiscardTimer-r16 ENUMERATED {supported} OPTIONAL, + continueEHC-Context-r16 ENUMERATED {supported} OPTIONAL, + ehc-r16 ENUMERATED {supported} OPTIONAL, + maxNumberEHC-Contexts-r16 ENUMERATED {cs2, cs4, cs8, cs16, cs32, cs64, cs128, cs256, cs512, + cs1024, cs2048, cs4096, cs8192, cs16384, cs32768, cs65536} OPTIONAL, + jointEHC-ROHC-Config-r16 ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationMoreThanTwoRLC-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-PDCP-PARAMETERS-STOP +-- TAG-PDCP-PARAMETERSMRDC-START + +PDCP-ParametersMRDC ::= SEQUENCE { + pdcp-DuplicationSplitSRB ENUMERATED {supported} OPTIONAL, + pdcp-DuplicationSplitDRB ENUMERATED {supported} OPTIONAL +} + +PDCP-ParametersMRDC-v1610 ::= SEQUENCE { + scg-DRB-NR-IAB-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-PDCP-PARAMETERSMRDC-STOP +-- TAG-PHY-PARAMETERS-START + +Phy-Parameters ::= SEQUENCE { + phy-ParametersCommon Phy-ParametersCommon OPTIONAL, + phy-ParametersXDD-Diff Phy-ParametersXDD-Diff OPTIONAL, + phy-ParametersFRX-Diff Phy-ParametersFRX-Diff OPTIONAL, + phy-ParametersFR1 Phy-ParametersFR1 OPTIONAL, + phy-ParametersFR2 Phy-ParametersFR2 OPTIONAL +} + +Phy-ParametersCommon ::= SEQUENCE { + csi-RS-CFRA-ForHO ENUMERATED {supported} OPTIONAL, + dynamicPRB-BundlingDL ENUMERATED {supported} OPTIONAL, + sp-CSI-ReportPUCCH ENUMERATED {supported} OPTIONAL, + sp-CSI-ReportPUSCH ENUMERATED {supported} OPTIONAL, + nzp-CSI-RS-IntefMgmt ENUMERATED {supported} OPTIONAL, + type2-SP-CSI-Feedback-LongPUCCH ENUMERATED {supported} OPTIONAL, + precoderGranularityCORESET ENUMERATED {supported} OPTIONAL, + dynamicHARQ-ACK-Codebook ENUMERATED {supported} OPTIONAL, + semiStaticHARQ-ACK-Codebook ENUMERATED {supported} OPTIONAL, + spatialBundlingHARQ-ACK ENUMERATED {supported} OPTIONAL, + dynamicBetaOffsetInd-HARQ-ACK-CSI ENUMERATED {supported} OPTIONAL, + pucch-Repetition-F1-3-4 ENUMERATED {supported} OPTIONAL, + ra-Type0-PUSCH ENUMERATED {supported} OPTIONAL, + dynamicSwitchRA-Type0-1-PDSCH ENUMERATED {supported} OPTIONAL, + dynamicSwitchRA-Type0-1-PUSCH ENUMERATED {supported} OPTIONAL, + pdsch-MappingTypeA ENUMERATED {supported} OPTIONAL, + pdsch-MappingTypeB ENUMERATED {supported} OPTIONAL, + interleavingVRB-ToPRB-PDSCH ENUMERATED {supported} OPTIONAL, + interSlotFreqHopping-PUSCH ENUMERATED {supported} OPTIONAL, + type1-PUSCH-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + type2-PUSCH-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + pusch-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + pdsch-RepetitionMultiSlots ENUMERATED {supported} OPTIONAL, + downlinkSPS ENUMERATED {supported} OPTIONAL, + configuredUL-GrantType1 ENUMERATED {supported} OPTIONAL, + configuredUL-GrantType2 ENUMERATED {supported} OPTIONAL, + pre-EmptIndication-DL ENUMERATED {supported} OPTIONAL, + cbg-TransIndication-DL ENUMERATED {supported} OPTIONAL, + cbg-TransIndication-UL ENUMERATED {supported} OPTIONAL, + cbg-FlushIndication-DL ENUMERATED {supported} OPTIONAL, + dynamicHARQ-ACK-CodeB-CBG-Retx-DL ENUMERATED {supported} OPTIONAL, + rateMatchingResrcSetSemi-Static ENUMERATED {supported} OPTIONAL, + rateMatchingResrcSetDynamic ENUMERATED {supported} OPTIONAL, + bwp-SwitchingDelay ENUMERATED {type1, type2} OPTIONAL, + ..., + [[ + dummy ENUMERATED {supported} OPTIONAL + ]], + [[ + maxNumberSearchSpaces ENUMERATED {n10} OPTIONAL, + rateMatchingCtrlResrcSetDynamic ENUMERATED {supported} OPTIONAL, + maxLayersMIMO-Indication ENUMERATED {supported} OPTIONAL + ]], + [[ + spCellPlacement CarrierAggregationVariant OPTIONAL + ]], + [[ + -- R1 9-1: Basic channel structure and procedure of 2-step RACH + twoStepRACH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-1: Monitoring DCI format 1_2 and DCI format 0_2 + dci-Format1-2And0-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-1a: Monitoring both DCI format 0_1/1_1 and DCI format 0_2/1_2 in the same search space + monitoringDCI-SameSearchSpace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-10: Type 2 configured grant release by DCI format 0_1 + type2-CG-ReleaseDCI-0-1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-11: Type 2 configured grant release by DCI format 0_2 + type2-CG-ReleaseDCI-0-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-3: SPS release by DCI format 1_1 + sps-ReleaseDCI-1-1-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-3a: SPS release by DCI format 1_2 + sps-ReleaseDCI-1-2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-8: CSI trigger states containing non-active BWP + csi-TriggerStateNon-ActiveBWP-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-2: Support up to 4 SMTCs configured for an IAB node MT per frequency location, including IAB-specific SMTC window periodicities + seperateSMTC-InterIAB-Support-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-3: Support RACH configuration separately from the RACH configuration for UE access, including new IAB-specific offset and scaling factors + seperateRACH-IAB-Support-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-5a: Support semi-static configuration/indication of UL-Flexible-DL slot formats for IAB-MT resources + ul-flexibleDL-SlotFormatSemiStatic-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-5b: Support dynamic indication of UL-Flexible-DL slot formats for IAB-MT resources + ul-flexibleDL-SlotFormatDynamics-IAB-r16 ENUMERATED {supported} OPTIONAL, + dft-S-OFDM-WaveformUL-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-6: Support DCI Format 2_5 based indication of soft resource availability to an IAB node + dci-25-AI-RNTI-Support-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-7: Support T_delta reception. + t-DeltaReceptionSupport-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 20-8: Support of Desired guard symbol reporting and provided guard symbok reception. + guardSymbolReportReception-IAB-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-8 HARQ-ACK codebook type and spatial bundling per PUCCH group + harqACK-CB-SpatialBundlingPUCCH-Group-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-2: Cross Slot Scheduling + crossSlotScheduling-r16 SEQUENCE { + non-SharedSpectrumChAccess-r16 ENUMERATED {supported} OPTIONAL, + sharedSpectrumChAccess-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + maxNumberSRS-PosPathLossEstimateAllServingCells-r16 ENUMERATED {n1, n4, n8, n16} OPTIONAL, + extendedCG-Periodicities-r16 ENUMERATED {supported} OPTIONAL, + extendedSPS-Periodicities-r16 ENUMERATED {supported} OPTIONAL, + codebookVariantsList-r16 CodebookVariantsList-r16 OPTIONAL, + -- R1 11-6: PUSCH repetition Type A + pusch-RepetitionTypeA-r16 SEQUENCE { + sharedSpectrumChAccess-r16 ENUMERATED {supported} OPTIONAL, + non-SharedSpectrumChAccess-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- R1 11-4b: DL priority indication in DCI with mixed DCI formats + dci-DL-PriorityIndicator-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-1a: UL priority indication in DCI with mixed DCI formats + dci-UL-PriorityIndicator-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1e: Maximum number of configured pathloss reference RSs for PUSCH/PUCCH/SRS by RRC for MAC-CE based pathloss reference RS update + maxNumberPathlossRS-Update-r16 ENUMERATED {n4, n8, n16, n32, n64} OPTIONAL, + + -- R1 18-9: Usage of the PDSCH starting time for HARQ-ACK type 2 codebook + type2-HARQ-ACK-Codebook-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1g-1: Resources for beam management, pathloss measurement, BFD, RLM and new beam identification across frequency ranges + maxTotalResourcesForAcrossFreqRanges-r16 SEQUENCE { + maxNumberResWithinSlotAcrossCC-AcrossFR-r16 ENUMERATED {n2, n4, n8, n12, n16, n32, n64, n128} OPTIONAL, + maxNumberResAcrossCC-AcrossFR-r16 ENUMERATED {n2, n4, n8, n12, n16, n32, n40, n48, n64, n72, n80, n96, n128, n256} + OPTIONAL + } OPTIONAL, + -- R1 16-2a-4: HARQ-ACK for multi-DCI based multi-TRP - separate + harqACK-separateMultiDCI-MultiTRP-r16 SEQUENCE { + maxNumberLongPUCCHs-r16 ENUMERATED {longAndLong, longAndShort, shortAndShort} OPTIONAL + } OPTIONAL, + -- R1 16-2a-4: HARQ-ACK for multi-DCI based multi-TRP - joint + harqACK-jointMultiDCI-MultiTRP-r16 ENUMERATED {supported} OPTIONAL, + -- R4 9-1: BWP switching on multiple CCs RRM requirements + bwp-SwitchingMultiCCs-r16 CHOICE { + type1-r16 ENUMERATED {us100, us200}, + type2-r16 ENUMERATED {us200, us400, us800, us1000} + } OPTIONAL + ]], + [[ + targetSMTC-SCG-r16 ENUMERATED {supported} OPTIONAL, + supportRepetitionZeroOffsetRV-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-12: in-order CBG-based re-transmission + cbg-TransInOrderPUSCH-UL-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R4 6-3: Dormant BWP switching on multiple CCs RRM requirements + bwp-SwitchingMultiDormancyCCs-r16 CHOICE { + type1-r16 ENUMERATED {us100, us200}, + type2-r16 ENUMERATED {us200, us400, us800, us1000} + } OPTIONAL, + -- R1 16-2a-8: Indicates that retransmission scheduled by a different CORESETPoolIndex for multi-DCI multi-TRP is not supported. + supportRetx-Diff-CoresetPool-Multi-DCI-TRP-r16 ENUMERATED {notSupported} OPTIONAL, + -- R1 22-10: Support of pdcch-MonitoringAnyOccasionsWithSpanGap in case of cross-carrier scheduling with different SCSs + pdcch-MonitoringAnyOccasionsWithSpanGapCrossCarrierSch-r16 ENUMERATED {mode2, mode3} OPTIONAL + ]] +} + +Phy-ParametersXDD-Diff ::= SEQUENCE { + dynamicSFI ENUMERATED {supported} OPTIONAL, + twoPUCCH-F0-2-ConsecSymbols ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUSCH ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUCCH ENUMERATED {supported} OPTIONAL, + ..., + [[ + dl-SchedulingOffset-PDSCH-TypeA ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeB ENUMERATED {supported} OPTIONAL, + ul-SchedulingOffset ENUMERATED {supported} OPTIONAL + ]] +} + +Phy-ParametersFRX-Diff ::= SEQUENCE { + dynamicSFI ENUMERATED {supported} OPTIONAL, + dummy1 BIT STRING (SIZE (2)) OPTIONAL, + twoFL-DMRS BIT STRING (SIZE (2)) OPTIONAL, + dummy2 BIT STRING (SIZE (2)) OPTIONAL, + dummy3 BIT STRING (SIZE (2)) OPTIONAL, + supportedDMRS-TypeDL ENUMERATED {type1, type1And2} OPTIONAL, + supportedDMRS-TypeUL ENUMERATED {type1, type1And2} OPTIONAL, + semiOpenLoopCSI ENUMERATED {supported} OPTIONAL, + csi-ReportWithoutPMI ENUMERATED {supported} OPTIONAL, + csi-ReportWithoutCQI ENUMERATED {supported} OPTIONAL, + onePortsPTRS BIT STRING (SIZE (2)) OPTIONAL, + twoPUCCH-F0-2-ConsecSymbols ENUMERATED {supported} OPTIONAL, + pucch-F2-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F3-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F4-WithFH ENUMERATED {supported} OPTIONAL, + pucch-F0-2WithoutFH ENUMERATED {notSupported} OPTIONAL, + pucch-F1-3-4WithoutFH ENUMERATED {notSupported} OPTIONAL, + mux-SR-HARQ-ACK-CSI-PUCCH-MultiPerSlot ENUMERATED {supported} OPTIONAL, + uci-CodeBlockSegmentation ENUMERATED {supported} OPTIONAL, + onePUCCH-LongAndShortFormat ENUMERATED {supported} OPTIONAL, + twoPUCCH-AnyOthersInSlot ENUMERATED {supported} OPTIONAL, + intraSlotFreqHopping-PUSCH ENUMERATED {supported} OPTIONAL, + pusch-LBRM ENUMERATED {supported} OPTIONAL, + pdcch-BlindDetectionCA INTEGER (4..16) OPTIONAL, + tpc-PUSCH-RNTI ENUMERATED {supported} OPTIONAL, + tpc-PUCCH-RNTI ENUMERATED {supported} OPTIONAL, + tpc-SRS-RNTI ENUMERATED {supported} OPTIONAL, + absoluteTPC-Command ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUSCH ENUMERATED {supported} OPTIONAL, + twoDifferentTPC-Loop-PUCCH ENUMERATED {supported} OPTIONAL, + pusch-HalfPi-BPSK ENUMERATED {supported} OPTIONAL, + pucch-F3-4-HalfPi-BPSK ENUMERATED {supported} OPTIONAL, + almostContiguousCP-OFDM-UL ENUMERATED {supported} OPTIONAL, + sp-CSI-RS ENUMERATED {supported} OPTIONAL, + sp-CSI-IM ENUMERATED {supported} OPTIONAL, + tdd-MultiDL-UL-SwitchPerSlot ENUMERATED {supported} OPTIONAL, + multipleCORESET ENUMERATED {supported} OPTIONAL, + ..., + [[ + csi-RS-IM-ReceptionForFeedback CSI-RS-IM-ReceptionForFeedback OPTIONAL, + csi-RS-ProcFrameworkForSRS CSI-RS-ProcFrameworkForSRS OPTIONAL, + csi-ReportFramework CSI-ReportFramework OPTIONAL, + mux-SR-HARQ-ACK-CSI-PUCCH-OncePerSlot SEQUENCE { + sameSymbol ENUMERATED {supported} OPTIONAL, + diffSymbol ENUMERATED {supported} OPTIONAL + } OPTIONAL, + mux-SR-HARQ-ACK-PUCCH ENUMERATED {supported} OPTIONAL, + mux-MultipleGroupCtrlCH-Overlap ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeA ENUMERATED {supported} OPTIONAL, + dl-SchedulingOffset-PDSCH-TypeB ENUMERATED {supported} OPTIONAL, + ul-SchedulingOffset ENUMERATED {supported} OPTIONAL, + dl-64QAM-MCS-TableAlt ENUMERATED {supported} OPTIONAL, + ul-64QAM-MCS-TableAlt ENUMERATED {supported} OPTIONAL, + cqi-TableAlt ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-TwoAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL, + twoFL-DMRS-TwoAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL, + oneFL-DMRS-ThreeAdditionalDMRS-UL ENUMERATED {supported} OPTIONAL + ]], + [[ + pdcch-BlindDetectionNRDC SEQUENCE { + pdcch-BlindDetectionMCG-UE INTEGER (1..15), + pdcch-BlindDetectionSCG-UE INTEGER (1..15) + } OPTIONAL, + mux-HARQ-ACK-PUSCH-DiffSymbol ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R1 11-1b: Type 1 HARQ-ACK codebook support for relative TDRA for DL + type1-HARQ-ACK-Codebook-r16 ENUMERATED {supported} OPTIONAL, + -- R1 11-8: Enhanced UL power control scheme + enhancedPowerControl-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1b-1: TCI state activation across multiple CCs + simultaneousTCI-ActMultipleCC-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1b-2: Spatial relation update across multiple CCs + simultaneousSpatialRelationMultipleCC-r16 ENUMERATED {supported} OPTIONAL, + cli-RSSI-FDM-DL-r16 ENUMERATED {supported} OPTIONAL, + cli-SRS-RSRP-FDM-DL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-3: Maximum MIMO Layer Adaptation + maxLayersMIMO-Adaptation-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-5: Configuration of aggregation factor per SPS configuration + aggregationFactorSPS-DL-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1g: Resources for beam management, pathloss measurement, BFD, RLM and new beam identification + maxTotalResourcesForOneFreqRange-r16 SEQUENCE { + maxNumberResWithinSlotAcrossCC-OneFR-r16 ENUMERATED {n2, n4, n8, n12, n16, n32, n64, n128} OPTIONAL, + maxNumberResAcrossCC-OneFR-r16 ENUMERATED {n2, n4, n8, n12, n16, n32, n40, n48, n64, n72, n80, n96, n128, n256} + OPTIONAL + } OPTIONAL, + -- R1 16-7: Extension of the maximum number of configured aperiodic CSI report settings + csi-ReportFrameworkExt-r16 CSI-ReportFrameworkExt-r16 OPTIONAL + ]], + [[ + twoTCI-Act-servingCellInCC-List-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +Phy-ParametersFR1 ::= SEQUENCE { + pdcch-MonitoringSingleOccasion ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL, + pdsch-256QAM-FR1 ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR1-PerSymbol ENUMERATED {n10, n20} OPTIONAL, + ..., + [[ + pdsch-RE-MappingFR1-PerSlot ENUMERATED {n16, n32, n48, n64, n80, n96, n112, n128, + n144, n160, n176, n192, n208, n224, n240, n256} OPTIONAL + ]] +} + +Phy-ParametersFR2 ::= SEQUENCE { + dummy ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR2-PerSymbol ENUMERATED {n6, n20} OPTIONAL, + ..., + [[ + pCell-FR2 ENUMERATED {supported} OPTIONAL, + pdsch-RE-MappingFR2-PerSlot ENUMERATED {n16, n32, n48, n64, n80, n96, n112, n128, + n144, n160, n176, n192, n208, n224, n240, n256} OPTIONAL + ]], + [[ + -- R1 16-1c: Support of default spatial relation and pathloss reference RS for dedicated-PUCCH/SRS and PUSCH + defaultSpatialRelationPathlossRS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 16-1d: Support of spatial relation update for AP-SRS via MAC CE + spatialRelationUpdateAP-SRS-r16 ENUMERATED {supported} OPTIONAL, + maxNumberSRS-PosSpatialRelationsAllServingCells-r16 ENUMERATED {n0, n1, n2, n4, n8, n16} OPTIONAL + ]] +} + +-- TAG-PHY-PARAMETERS-STOP +-- TAG-PHY-PARAMETERSMRDC-START + +Phy-ParametersMRDC ::= SEQUENCE { + naics-Capability-List SEQUENCE (SIZE (1..maxNrofNAICS-Entries)) OF NAICS-Capability-Entry OPTIONAL, + ..., + [[ + spCellPlacement CarrierAggregationVariant OPTIONAL + ]], + [[ + -- R1 18-3b: Semi-statically configured LTE UL transmissions in all UL subframes not limited to tdm-pattern in case of TDD PCell + tdd-PCellUL-TX-AllUL-Subframe-r16 ENUMERATED {supported} OPTIONAL, + -- R1 18-3a: Semi-statically configured LTE UL transmissions in all UL subframes not limited to tdm-pattern in case of FDD PCell + fdd-PCellUL-TX-AllUL-Subframe-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +NAICS-Capability-Entry ::= SEQUENCE { + numberOfNAICS-CapableCC INTEGER(1..5), + numberOfAggregatedPRB ENUMERATED {n50, n75, n100, n125, n150, n175, n200, n225, + n250, n275, n300, n350, n400, n450, n500, spare}, + ... +} + +-- TAG-PHY-PARAMETERSMRDC-STOP +-- TAG-PHY-PARAMETERSSHAREDSPECTRUMCHACCESS-START + +Phy-ParametersSharedSpectrumChAccess-r16 ::= SEQUENCE { + -- 10-32 (1-2): SS block based SINR measurement (SS-SINR) for unlicensed spectrum + ss-SINR-Meas-r16 ENUMERATED {supported} OPTIONAL, + -- 10-33 (2-32a): Semi-persistent CSI report on PUCCH for unlicensed spectrum + sp-CSI-ReportPUCCH-r16 ENUMERATED {supported} OPTIONAL, + -- 10-33a (2-32b): Semi-persistent CSI report on PUSCH for unlicensed spectrum + sp-CSI-ReportPUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- 10-34 (3-6): Dynamic SFI monitoring for unlicensed spectrum + dynamicSFI-r16 ENUMERATED {supported} OPTIONAL, + -- 10-35c (4-19c): SR/HARQ-ACK/CSI multiplexing once per slot using a PUCCH (or HARQ-ACK/CSI piggybacked on a PUSCH) when SR/HARQ- + -- ACK/CSI are supposed to be sent with different starting symbols in a slot for unlicensed spectrum + -- 10-35 (4-19): SR/HARQ-ACK/CSI multiplexing once per slot using a PUCCH (or HARQ-ACK/CSI piggybacked on a PUSCH) when SR/HARQ- + -- ACK/CSI are supposed to be sent with the same starting symbol on the PUCCH resources in a slot for unlicensed spectrum + mux-SR-HARQ-ACK-CSI-PUCCH-OncePerSlot-r16 SEQUENCE { + sameSymbol-r16 ENUMERATED {supported} OPTIONAL, + diffSymbol-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + -- 10-35a (4-19a): Overlapping PUCCH resources have different starting symbols in a slot for unlicensed spectrum + mux-SR-HARQ-ACK-PUCCH-r16 ENUMERATED {supported} OPTIONAL, + -- 10-35b (4-19b): SR/HARQ-ACK/CSI multiplexing more than once per slot using a PUCCH (or HARQ-ACK/CSI piggybacked on a PUSCH) when + -- SR/HARQ ACK/CSI are supposed to be sent with the same or different starting symbol in a slot for unlicensed spectrum + mux-SR-HARQ-ACK-CSI-PUCCH-MultiPerSlot-r16 ENUMERATED {supported} OPTIONAL, + -- 10-36 (4-28): HARQ-ACK multiplexing on PUSCH with different PUCCH/PUSCH starting OFDM symbols for unlicensed spectrum + mux-HARQ-ACK-PUSCH-DiffSymbol-r16 ENUMERATED {supported} OPTIONAL, + -- 10-37 (4-23): Repetitions for PUCCH format 1, 3, and 4 over multiple slots with K = 2, 4, 8 for unlicensed spectrum + pucch-Repetition-F1-3-4-r16 ENUMERATED {supported} OPTIONAL, + -- 10-38 (5-14): Type 1 configured PUSCH repetitions over multiple slots for unlicensed spectrum + type1-PUSCH-RepetitionMultiSlots-r16 ENUMERATED {supported} OPTIONAL, + -- 10-39 (5-16): Type 2 configured PUSCH repetitions over multiple slots for unlicensed spectrum + type2-PUSCH-RepetitionMultiSlots-r16 ENUMERATED {supported} OPTIONAL, + -- 10-40 (5-17): PUSCH repetitions over multiple slots for unlicensed spectrum + pusch-RepetitionMultiSlots-r16 ENUMERATED {supported} OPTIONAL, + -- 10-40a (5-17a): PDSCH repetitions over multiple slots for unlicensed spectrum + pdsch-RepetitionMultiSlots-r16 ENUMERATED {supported} OPTIONAL, + -- 10-41 (5-18): DL SPS + downlinkSPS-r16 ENUMERATED {supported} OPTIONAL, + -- 10-42 (5-19): Type 1 Configured UL grant + configuredUL-GrantType1-r16 ENUMERATED {supported} OPTIONAL, + -- 10-43 (5-20): Type 2 Configured UL grant + configuredUL-GrantType2-r16 ENUMERATED {supported} OPTIONAL, + -- 10-44 (5-21): Pre-emption indication for DL + pre-EmptIndication-DL-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-PHY-PARAMETERSSHAREDSPECTRUMCHACCESS-STOP +-- TAG-POWSAV-PARAMETERS-START + +PowSav-Parameters-r16 ::= SEQUENCE { + powSav-ParametersCommon-r16 PowSav-ParametersCommon-r16 OPTIONAL, + powSav-ParametersFRX-Diff-r16 PowSav-ParametersFRX-Diff-r16 OPTIONAL, + ... +} + +PowSav-ParametersCommon-r16 ::= SEQUENCE { + drx-Preference-r16 ENUMERATED {supported} OPTIONAL, + maxCC-Preference-r16 ENUMERATED {supported} OPTIONAL, + releasePreference-r16 ENUMERATED {supported} OPTIONAL, + -- R1 19-4a: UE assistance information + minSchedulingOffsetPreference-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +PowSav-ParametersFRX-Diff-r16 ::= SEQUENCE { + maxBW-Preference-r16 ENUMERATED {supported} OPTIONAL, + maxMIMO-LayerPreference-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-POWSAV-PARAMETERS-STOP +-- TAG-PROCESSINGPARAMETERS-START + +ProcessingParameters ::= SEQUENCE { + fallback ENUMERATED {sc, cap1-only}, + differentTB-PerSlot SEQUENCE { + upto1 NumberOfCarriers OPTIONAL, + upto2 NumberOfCarriers OPTIONAL, + upto4 NumberOfCarriers OPTIONAL, + upto7 NumberOfCarriers OPTIONAL + } OPTIONAL +} + +NumberOfCarriers ::= INTEGER (1..16) + +-- TAG-PROCESSINGPARAMETERS-STOP +-- TAG-RAT-TYPE-START + +RAT-Type ::= ENUMERATED {nr, eutra-nr, eutra, utra-fdd-v1610, ...} + +-- TAG-RAT-TYPE-STOP +-- TAG-RF-PARAMETERS-START + +RF-Parameters ::= SEQUENCE { + supportedBandListNR SEQUENCE (SIZE (1..maxBands)) OF BandNR, + supportedBandCombinationList BandCombinationList OPTIONAL, + appliedFreqBandListFilter FreqBandList OPTIONAL, + ..., + [[ + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL, + srs-SwitchingTimeRequested ENUMERATED {true} OPTIONAL + ]], + [[ + supportedBandCombinationList-v1550 BandCombinationList-v1550 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationListSidelinkEUTRA-NR-r16 BandCombinationListSidelinkEUTRA-NR-r16 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-r16 BandCombinationList-UplinkTxSwitch-r16 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1630 BandCombinationList-v1630 OPTIONAL, + supportedBandCombinationListSidelinkEUTRA-NR-v1630 BandCombinationListSidelinkEUTRA-NR-v1630 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-v1630 BandCombinationList-UplinkTxSwitch-v1630 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1640 BandCombinationList-v1640 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-v1640 BandCombinationList-UplinkTxSwitch-v1640 OPTIONAL + ]] + +} + +BandNR ::= SEQUENCE { + bandNR FreqBandIndicatorNR, + modifiedMPR-Behaviour BIT STRING (SIZE (8)) OPTIONAL, + mimo-ParametersPerBand MIMO-ParametersPerBand OPTIONAL, + extendedCP ENUMERATED {supported} OPTIONAL, + multipleTCI ENUMERATED {supported} OPTIONAL, + bwp-WithoutRestriction ENUMERATED {supported} OPTIONAL, + bwp-SameNumerology ENUMERATED {upto2, upto4} OPTIONAL, + bwp-DiffNumerology ENUMERATED {upto4} OPTIONAL, + crossCarrierScheduling-SameSCS ENUMERATED {supported} OPTIONAL, + pdsch-256QAM-FR2 ENUMERATED {supported} OPTIONAL, + pusch-256QAM ENUMERATED {supported} OPTIONAL, + ue-PowerClass ENUMERATED {pc1, pc2, pc3, pc4} OPTIONAL, + rateMatchingLTE-CRS ENUMERATED {supported} OPTIONAL, + channelBWs-DL CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (10)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (3)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (3)) OPTIONAL + } + } OPTIONAL, + channelBWs-UL CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (10)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (10)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (3)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (3)) OPTIONAL + } + } OPTIONAL, + ..., + [[ + maxUplinkDutyCycle-PC2-FR1 ENUMERATED {n60, n70, n80, n90, n100} OPTIONAL + ]], + [[ + pucch-SpatialRelInfoMAC-CE ENUMERATED {supported} OPTIONAL, + powerBoosting-pi2BPSK ENUMERATED {supported} OPTIONAL + ]], + [[ + maxUplinkDutyCycle-FR2 ENUMERATED {n15, n20, n25, n30, n40, n50, n60, n70, n80, n90, n100} OPTIONAL + ]], + [[ + channelBWs-DL-v1590 CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (16)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (8)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (8)) OPTIONAL + } + } OPTIONAL, + channelBWs-UL-v1590 CHOICE { + fr1 SEQUENCE { + scs-15kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz BIT STRING (SIZE (16)) OPTIONAL + }, + fr2 SEQUENCE { + scs-60kHz BIT STRING (SIZE (8)) OPTIONAL, + scs-120kHz BIT STRING (SIZE (8)) OPTIONAL + } + } OPTIONAL + ]], + [[ + asymmetricBandwidthCombinationSet BIT STRING (SIZE (1..32)) OPTIONAL + ]], + [[ + -- R1 10: NR-unlicensed + sharedSpectrumChAccessParamsPerBand-r16 SharedSpectrumChAccessParamsPerBand-r16 OPTIONAL, + -- R1 11-7b: Independent cancellation of the overlapping PUSCHs in an intra-band UL CA + cancelOverlappingPUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-1: Multiple LTE-CRS rate matching patterns + multipleRateMatchingEUTRA-CRS-r16 SEQUENCE { + maxNumberPatterns-r16 INTEGER (2..6), + maxNumberNon-OverlapPatterns-r16 INTEGER (1..3) + } OPTIONAL, + -- R1 14-1a: Two LTE-CRS overlapping rate matching patterns within a part of NR carrier using 15 kHz overlapping with a LTE carrier + overlapRateMatchingEUTRA-CRS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-2: PDSCH Type B mapping of length 9 and 10 OFDM symbols + pdsch-MappingTypeB-Alt-r16 ENUMERATED {supported} OPTIONAL, + -- R1 14-3: One slot periodic TRS configuration for FR1 + oneSlotPeriodicTRS-r16 ENUMERATED {supported} OPTIONAL, + olpc-SRS-Pos-r16 OLPC-SRS-Pos-r16 OPTIONAL, + spatialRelationsSRS-Pos-r16 SpatialRelationsSRS-Pos-r16 OPTIONAL, + simulSRS-MIMO-TransWithinBand-r16 ENUMERATED {n2} OPTIONAL, + channelBW-DL-IAB-r16 CHOICE { + fr1-100mhz SEQUENCE { + scs-15kHz ENUMERATED {supported} OPTIONAL, + scs-30kHz ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL + }, + fr2-200mhz SEQUENCE { + scs-60kHz ENUMERATED {supported} OPTIONAL, + scs-120kHz ENUMERATED {supported} OPTIONAL + } + } OPTIONAL, + channelBW-UL-IAB-r16 CHOICE { + fr1-100mhz SEQUENCE { + scs-15kHz ENUMERATED {supported} OPTIONAL, + scs-30kHz ENUMERATED {supported} OPTIONAL, + scs-60kHz ENUMERATED {supported} OPTIONAL + }, + fr2-200mhz SEQUENCE { + scs-60kHz ENUMERATED {supported} OPTIONAL, + scs-120kHz ENUMERATED {supported} OPTIONAL + } + } OPTIONAL, + rasterShift7dot5-IAB-r16 ENUMERATED {supported} OPTIONAL, + ue-PowerClass-v1610 ENUMERATED {pc1dot5} OPTIONAL, + condHandover-r16 ENUMERATED {supported} OPTIONAL, + condHandoverFailure-r16 ENUMERATED {supported} OPTIONAL, + condHandoverTwoTriggerEvents-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChange-r16 ENUMERATED {supported} OPTIONAL, + condPSCellChangeTwoTriggerEvents-r16 ENUMERATED {supported} OPTIONAL, + mpr-PowerBoost-FR2-r16 ENUMERATED {supported} OPTIONAL, + + -- R1 11-9: Multiple active configured grant configurations for a BWP of a serving cell + activeConfiguredGrant-r16 SEQUENCE { + maxNumberConfigsPerBWP-r16 ENUMERATED {n1, n2, n4, n8, n12}, + maxNumberConfigsAllCC-r16 INTEGER (2..32) + } OPTIONAL, + -- R1 11-9a: Joint release in a DCI for two or more configured grant Type 2 configurations for a given BWP of a serving cell + jointReleaseConfiguredGrantType2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 12-2: Multiple SPS configurations + sps-r16 SEQUENCE { + maxNumberConfigsPerBWP-r16 INTEGER (1..8), + maxNumberConfigsAllCC-r16 INTEGER (2..32) + } OPTIONAL, + -- R1 12-2a: Joint release in a DCI for two or more SPS configurations for a given BWP of a serving cell + jointReleaseSPS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 13-19: Simultaneous positioning SRS and MIMO SRS transmission within a band across multiple CCs + simulSRS-TransWithinBand-r16 ENUMERATED {n2} OPTIONAL, + trs-AdditionalBandwidth-r16 ENUMERATED {trs-AddBW-Set1, trs-AddBW-Set2} OPTIONAL, + handoverIntraF-IAB-r16 ENUMERATED {supported} OPTIONAL + ]], + [[ + -- R1 22-5a: Simultaneous transmission of SRS for antenna switching and SRS for CB/NCB /BM for intra-band UL CA + -- R1 22-5c: Simultaneous transmission of SRS for antenna switching and SRS for antenna switching for intra-band UL CA + simulTX-SRS-AntSwitchingIntraBandUL-CA-r16 SimulSRS-ForAntennaSwitching-r16 OPTIONAL, + -- R1 10: NR-unlicensed + sharedSpectrumChAccessParamsPerBand-v1630 SharedSpectrumChAccessParamsPerBand-v1630 OPTIONAL + ]], + [[ + handoverUTRA-FDD-r16 ENUMERATED {supported} OPTIONAL, + -- R4 7-4: Report the shorter transient capability supported by the UE: 2, 4 or 7us + enhancedUL-TransientPeriod-r16 ENUMERATED {us2, us4, us7} OPTIONAL, + sharedSpectrumChAccessParamsPerBand-v1640 SharedSpectrumChAccessParamsPerBand-v1640 OPTIONAL + ]] +} + +-- TAG-RF-PARAMETERS-STOP +-- TAG-RF-PARAMETERSMRDC-START + +RF-ParametersMRDC ::= SEQUENCE { + supportedBandCombinationList BandCombinationList OPTIONAL, + appliedFreqBandListFilter FreqBandList OPTIONAL, + ..., + [[ + srs-SwitchingTimeRequested ENUMERATED {true} OPTIONAL, + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1550 BandCombinationList-v1550 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL, + supportedBandCombinationListNEDC-Only BandCombinationList OPTIONAL + ]], + [[ + supportedBandCombinationList-v1570 BandCombinationList-v1570 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1580 BandCombinationList-v1580 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1590 BandCombinationList-v1590 OPTIONAL + ]], + [[ + supportedBandCombinationListNEDC-Only-v15a0 SEQUENCE { + supportedBandCombinationList-v1540 BandCombinationList-v1540 OPTIONAL, + supportedBandCombinationList-v1560 BandCombinationList-v1560 OPTIONAL, + supportedBandCombinationList-v1570 BandCombinationList-v1570 OPTIONAL, + supportedBandCombinationList-v1580 BandCombinationList-v1580 OPTIONAL, + supportedBandCombinationList-v1590 BandCombinationList-v1590 OPTIONAL + } OPTIONAL + ]], + [[ + supportedBandCombinationList-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationListNEDC-Only-v1610 BandCombinationList-v1610 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-r16 BandCombinationList-UplinkTxSwitch-r16 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1630 BandCombinationList-v1630 OPTIONAL, + supportedBandCombinationListNEDC-Only-v1630 BandCombinationList-v1630 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-v1630 BandCombinationList-UplinkTxSwitch-v1630 OPTIONAL + ]], + [[ + supportedBandCombinationList-v1640 BandCombinationList-v1640 OPTIONAL, + supportedBandCombinationListNEDC-Only-v1640 BandCombinationList-v1640 OPTIONAL, + supportedBandCombinationList-UplinkTxSwitch-v1640 BandCombinationList-UplinkTxSwitch-v1640 OPTIONAL + ]] +} + +-- TAG-RF-PARAMETERSMRDC-STOP +-- TAG-RLC-PARAMETERS-START + +RLC-Parameters ::= SEQUENCE { + am-WithShortSN ENUMERATED {supported} OPTIONAL, + um-WithShortSN ENUMERATED {supported} OPTIONAL, + um-WithLongSN ENUMERATED {supported} OPTIONAL, + ..., + [[ + extendedT-PollRetransmit-r16 ENUMERATED {supported} OPTIONAL, + extendedT-StatusProhibit-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-RLC-PARAMETERS-STOP +-- TAG-SDAP-PARAMETERS-START + +SDAP-Parameters ::= SEQUENCE { + as-ReflectiveQoS ENUMERATED {true} OPTIONAL, + ..., + [[ + sdap-QOS-IAB-r16 ENUMERATED {supported} OPTIONAL, + sdapHeaderIAB-r16 ENUMERATED {supported} OPTIONAL + ]] + +} + +-- TAG-SDAP-PARAMETERS-STOP +-- TAG-SIDELINKPARAMETERS-START + +SidelinkParameters-r16 ::= SEQUENCE { + sidelinkParametersNR-r16 SidelinkParametersNR-r16 OPTIONAL, + sidelinkParametersEUTRA-r16 SidelinkParametersEUTRA-r16 OPTIONAL +} + +SidelinkParametersNR-r16 ::= SEQUENCE { + rlc-ParametersSidelink-r16 RLC-ParametersSidelink-r16 OPTIONAL, + mac-ParametersSidelink-r16 MAC-ParametersSidelink-r16 OPTIONAL, + fdd-Add-UE-Sidelink-Capabilities-r16 UE-SidelinkCapabilityAddXDD-Mode-r16 OPTIONAL, + tdd-Add-UE-Sidelink-Capabilities-r16 UE-SidelinkCapabilityAddXDD-Mode-r16 OPTIONAL, + supportedBandListSidelink-r16 SEQUENCE (SIZE (1..maxBands)) OF BandSidelink-r16 OPTIONAL, + ... +} + +SidelinkParametersEUTRA-r16 ::= SEQUENCE { + sl-ParametersEUTRA1-r16 OCTET STRING OPTIONAL, + sl-ParametersEUTRA2-r16 OCTET STRING OPTIONAL, + sl-ParametersEUTRA3-r16 OCTET STRING OPTIONAL, + supportedBandListSidelinkEUTRA-r16 SEQUENCE (SIZE (1..maxBandsEUTRA)) OF BandSidelinkEUTRA-r16 OPTIONAL, + ... +} + +RLC-ParametersSidelink-r16 ::= SEQUENCE { + am-WithLongSN-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + um-WithLongSN-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +MAC-ParametersSidelink-r16 ::= SEQUENCE { + mac-ParametersSidelinkCommon-r16 MAC-ParametersSidelinkCommon-r16 OPTIONAL, + mac-ParametersSidelinkXDD-Diff-r16 MAC-ParametersSidelinkXDD-Diff-r16 OPTIONAL, + ... +} + +UE-SidelinkCapabilityAddXDD-Mode-r16 ::= SEQUENCE { + mac-ParametersSidelinkXDD-Diff-r16 MAC-ParametersSidelinkXDD-Diff-r16 OPTIONAL +} + +MAC-ParametersSidelinkCommon-r16 ::= SEQUENCE { + lcp-RestrictionSidelink-r16 ENUMERATED {supported} OPTIONAL, + multipleConfiguredGrantsSidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +MAC-ParametersSidelinkXDD-Diff-r16 ::= SEQUENCE { + multipleSR-ConfigurationsSidelink-r16 ENUMERATED {supported} OPTIONAL, + logicalChannelSR-DelayTimerSidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +BandSidelinkEUTRA-r16 ::= SEQUENCE { + freqBandSidelinkEUTRA-r16 FreqBandIndicatorEUTRA, + -- R1 15-7: Transmitting LTE sidelink mode 3 scheduled by NR Uu + gnb-ScheduledMode3SidelinkEUTRA-r16 SEQUENCE { + gnb-ScheduledMode3DelaySidelinkEUTRA-r16 ENUMERATED {ms0, ms0dot25, ms0dot5, ms0dot625, ms0dot75, ms1, + ms1dot25, ms1dot5, ms1dot75, ms2, ms2dot5, ms3, ms4, + ms5, ms6, ms8, ms10, ms20} + } OPTIONAL, + -- R1 15-9: Transmitting LTE sidelink mode 4 configured by NR Uu + gnb-ScheduledMode4SidelinkEUTRA-r16 ENUMERATED {supported} OPTIONAL +} + +BandSidelink-r16 ::= SEQUENCE { + freqBandSidelink-r16 FreqBandIndicatorNR, + --15-1 + sl-Reception-r16 SEQUENCE { + harq-RxProcessSidelink-r16 ENUMERATED {n16, n24, n32, n48, n64}, + pscch-RxSidelink-r16 ENUMERATED {value1, value2}, + scs-CP-PatternRxSidelink-r16 CHOICE { + fr1-r16 SEQUENCE { + scs-15kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + }, + fr2-r16 SEQUENCE { + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-120kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + } + } OPTIONAL, + extendedCP-RxSidelink-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-2 + sl-TransmissionMode1-r16 SEQUENCE { + harq-TxProcessModeOneSidelink-r16 ENUMERATED {n8, n16}, + scs-CP-PatternTxSidelinkModeOne-r16 CHOICE { + fr1-r16 SEQUENCE { + scs-15kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + }, + fr2-r16 SEQUENCE { + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-120kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + } + }, + extendedCP-TxSidelink-r16 ENUMERATED {supported} OPTIONAL, + harq-ReportOnPUCCH-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-4 + sync-Sidelink-r16 SEQUENCE { + gNB-Sync-r16 ENUMERATED {supported} OPTIONAL, + gNB-GNSS-UE-SyncWithPriorityOnGNB-ENB-r16 ENUMERATED {supported} OPTIONAL, + gNB-GNSS-UE-SyncWithPriorityOnGNSS-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-10 + sl-Tx-256QAM-r16 ENUMERATED {supported} OPTIONAL, + --15-11 + psfch-FormatZeroSidelink-r16 SEQUENCE { + psfch-RxNumber ENUMERATED {n5, n15, n25, n32, n35, n45, n50, n64}, + psfch-TxNumber ENUMERATED {n4, n8, n16} + } OPTIONAL, + --15-12 + lowSE-64QAM-MCS-TableSidelink-r16 ENUMERATED {supported} OPTIONAL, + --15-15 + enb-sync-Sidelink-r16 ENUMERATED {supported} OPTIONAL, + ..., + [[ + --15-3 + sl-TransmissionMode2-r16 SEQUENCE { + harq-TxProcessModeTwoSidelink-r16 ENUMERATED {n8, n16}, + scs-CP-PatternTxSidelinkModeTwo-r16 ENUMERATED {supported} OPTIONAL, + dl-openLoopPC-Sidelink-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-5 + congestionControlSidelink-r16 SEQUENCE { + cbr-ReportSidelink-r16 ENUMERATED {supported} OPTIONAL, + cbr-CR-TimeLimitSidelink-r16 ENUMERATED {time1, time2} + } OPTIONAL, + --15-22 + fewerSymbolSlotSidelink-r16 ENUMERATED {supported} OPTIONAL, + --15-23 + sl-openLoopPC-RSRP-ReportSidelink-r16 ENUMERATED {supported} OPTIONAL, + --13-1 + sl-Rx-256QAM-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-SIDELINKPARAMETERS-STOP +-- TAG-SON-PARAMETERS-START + +SON-Parameters-r16 ::= SEQUENCE { + rach-Report-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-SON-PARAMETERS-STOP +-- TAG-SPATIALRELATIONSSRS-POS-START + +SpatialRelationsSRS-Pos-r16 ::= SEQUENCE { + spatialRelation-SRS-PosBasedOnSSB-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnCSI-RS-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnPRS-Serving-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnSRS-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnSSB-Neigh-r16 ENUMERATED {supported} OPTIONAL, + spatialRelation-SRS-PosBasedOnPRS-Neigh-r16 ENUMERATED {supported} OPTIONAL +} + +--TAG-SPATIALRELATIONSSRS-POS-STOP +-- TAG-SRS-SWITCHINGTIMENR-START + +SRS-SwitchingTimeNR ::= SEQUENCE { + switchingTimeDL ENUMERATED {n0us, n30us, n100us, n140us, n200us, n300us, n500us, n900us} OPTIONAL, + switchingTimeUL ENUMERATED {n0us, n30us, n100us, n140us, n200us, n300us, n500us, n900us} OPTIONAL +} + +-- TAG-SRS-SWITCHINGTIMENR-STOP +-- TAG-SRS-SWITCHINGTIMEEUTRA-START + +SRS-SwitchingTimeEUTRA ::= SEQUENCE { + switchingTimeDL ENUMERATED {n0, n0dot5, n1, n1dot5, n2, n2dot5, n3, n3dot5, n4, n4dot5, n5, n5dot5, n6, n6dot5, n7} + OPTIONAL, + switchingTimeUL ENUMERATED {n0, n0dot5, n1, n1dot5, n2, n2dot5, n3, n3dot5, n4, n4dot5, n5, n5dot5, n6, n6dot5, n7} + OPTIONAL +} +-- TAG-SRS-SWITCHINGTIMEEUTRA-STOP +-- TAG-SUPPORTEDBANDWIDTH-START + +SupportedBandwidth ::= CHOICE { + fr1 ENUMERATED {mhz5, mhz10, mhz15, mhz20, mhz25, mhz30, mhz40, mhz50, mhz60, mhz80, mhz100}, + fr2 ENUMERATED {mhz50, mhz100, mhz200, mhz400} +} + +-- TAG-SUPPORTEDBANDWIDTH-STOP +-- TAG-UE-BASEDPERFMEAS-PARAMETERS-START + +UE-BasedPerfMeas-Parameters-r16 ::= SEQUENCE { + barometerMeasReport-r16 ENUMERATED {supported} OPTIONAL, + immMeasBT-r16 ENUMERATED {supported} OPTIONAL, + immMeasWLAN-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasBT-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasurements-r16 ENUMERATED {supported} OPTIONAL, + loggedMeasWLAN-r16 ENUMERATED {supported} OPTIONAL, + orientationMeasReport-r16 ENUMERATED {supported} OPTIONAL, + speedMeasReport-r16 ENUMERATED {supported} OPTIONAL, + gnss-Location-r16 ENUMERATED {supported} OPTIONAL, + ulPDCP-Delay-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +-- TAG-UE-BASEDPERFMEAS-PARAMETERS-STOP +-- TAG-UE-CAPABILITYRAT-CONTAINERLIST-START + +UE-CapabilityRAT-ContainerList ::= SEQUENCE (SIZE (0..maxRAT-CapabilityContainers)) OF UE-CapabilityRAT-Container + +UE-CapabilityRAT-Container ::= SEQUENCE { + rat-Type RAT-Type, + ue-CapabilityRAT-Container OCTET STRING +} + +-- TAG-UE-CAPABILITYRAT-CONTAINERLIST-STOP +-- TAG-UE-CAPABILITYRAT-REQUESTLIST-START + +UE-CapabilityRAT-RequestList ::= SEQUENCE (SIZE (1..maxRAT-CapabilityContainers)) OF UE-CapabilityRAT-Request + +UE-CapabilityRAT-Request ::= SEQUENCE { + rat-Type RAT-Type, + capabilityRequestFilter OCTET STRING OPTIONAL, -- Need N + ... +} + +-- TAG-UE-CAPABILITYRAT-REQUESTLIST-STOP +-- TAG-UE-CAPABILITYREQUESTFILTERCOMMON-START + +UE-CapabilityRequestFilterCommon ::= SEQUENCE { + mrdc-Request SEQUENCE { + omitEN-DC ENUMERATED {true} OPTIONAL, -- Need N + includeNR-DC ENUMERATED {true} OPTIONAL, -- Need N + includeNE-DC ENUMERATED {true} OPTIONAL -- Need N + } OPTIONAL, -- Need N + ..., + [[ + codebookTypeRequest-r16 SEQUENCE { + type1-SinglePanel-r16 ENUMERATED {true} OPTIONAL, -- Need N + type1-MultiPanel-r16 ENUMERATED {true} OPTIONAL, -- Need N + type2-r16 ENUMERATED {true} OPTIONAL, -- Need N + type2-PortSelection-r16 ENUMERATED {true} OPTIONAL -- Need N + } OPTIONAL, -- Need N + uplinkTxSwitchRequest-r16 ENUMERATED {true} OPTIONAL -- Need N + ]] +} + +-- TAG-UE-CAPABILITYREQUESTFILTERCOMMON-STOP +-- TAG-UE-CAPABILITYREQUESTFILTERNR-START + +UE-CapabilityRequestFilterNR ::= SEQUENCE { + frequencyBandListFilter FreqBandList OPTIONAL, -- Need N + nonCriticalExtension UE-CapabilityRequestFilterNR-v1540 OPTIONAL +} + +UE-CapabilityRequestFilterNR-v1540 ::= SEQUENCE { + srs-SwitchingTimeRequest ENUMERATED {true} OPTIONAL, -- Need N + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UE-CAPABILITYREQUESTFILTERNR-STOP +-- TAG-UE-MRDC-CAPABILITY-START + +UE-MRDC-Capability ::= SEQUENCE { + measAndMobParametersMRDC MeasAndMobParametersMRDC OPTIONAL, + phy-ParametersMRDC-v1530 Phy-ParametersMRDC OPTIONAL, + rf-ParametersMRDC RF-ParametersMRDC, + generalParametersMRDC GeneralParametersMRDC-XDD-Diff OPTIONAL, + fdd-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-MRDC-Capabilities UE-MRDC-CapabilityAddFRX-Mode OPTIONAL, + featureSetCombinations SEQUENCE (SIZE (1..maxFeatureSetCombinations)) OF FeatureSetCombination OPTIONAL, + pdcp-ParametersMRDC-v1530 PDCP-ParametersMRDC OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension UE-MRDC-Capability-v1560 OPTIONAL +} + +UE-MRDC-Capability-v1560 ::= SEQUENCE { + receivedFilters OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL, + measAndMobParametersMRDC-v1560 MeasAndMobParametersMRDC-v1560 OPTIONAL, + fdd-Add-UE-MRDC-Capabilities-v1560 UE-MRDC-CapabilityAddXDD-Mode-v1560 OPTIONAL, + tdd-Add-UE-MRDC-Capabilities-v1560 UE-MRDC-CapabilityAddXDD-Mode-v1560 OPTIONAL, + nonCriticalExtension UE-MRDC-Capability-v1610 OPTIONAL +} + +UE-MRDC-Capability-v1610 ::= SEQUENCE { + measAndMobParametersMRDC-v1610 MeasAndMobParametersMRDC-v1610 OPTIONAL, + generalParametersMRDC-v1610 GeneralParametersMRDC-v1610 OPTIONAL, + pdcp-ParametersMRDC-v1610 PDCP-ParametersMRDC-v1610 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-MRDC-CapabilityAddXDD-Mode ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff MeasAndMobParametersMRDC-XDD-Diff OPTIONAL, + generalParametersMRDC-XDD-Diff GeneralParametersMRDC-XDD-Diff OPTIONAL +} + +UE-MRDC-CapabilityAddXDD-Mode-v1560 ::= SEQUENCE { + measAndMobParametersMRDC-XDD-Diff-v1560 MeasAndMobParametersMRDC-XDD-Diff-v1560 OPTIONAL +} + +UE-MRDC-CapabilityAddFRX-Mode ::= SEQUENCE { + measAndMobParametersMRDC-FRX-Diff MeasAndMobParametersMRDC-FRX-Diff +} + + +GeneralParametersMRDC-XDD-Diff ::= SEQUENCE { + splitSRB-WithOneUL-Path ENUMERATED {supported} OPTIONAL, + splitDRB-withUL-Both-MCG-SCG ENUMERATED {supported} OPTIONAL, + srb3 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + ... +} + +GeneralParametersMRDC-v1610 ::= SEQUENCE { + f1c-OverEUTRA-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-UE-MRDC-CAPABILITY-STOP +-- TAG-UE-NR-CAPABILITY-START + +UE-NR-Capability ::= SEQUENCE { + accessStratumRelease AccessStratumRelease, + pdcp-Parameters PDCP-Parameters, + rlc-Parameters RLC-Parameters OPTIONAL, + mac-Parameters MAC-Parameters OPTIONAL, + phy-Parameters Phy-Parameters, + rf-Parameters RF-Parameters, + measAndMobParameters MeasAndMobParameters OPTIONAL, + fdd-Add-UE-NR-Capabilities UE-NR-CapabilityAddXDD-Mode OPTIONAL, + tdd-Add-UE-NR-Capabilities UE-NR-CapabilityAddXDD-Mode OPTIONAL, + fr1-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + fr2-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + featureSets FeatureSets OPTIONAL, + featureSetCombinations SEQUENCE (SIZE (1..maxFeatureSetCombinations)) OF FeatureSetCombination OPTIONAL, + lateNonCriticalExtension OCTET STRING (CONTAINING UE-NR-Capability-v15c0) OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1530 OPTIONAL +} + +-- Regular non-critical extensions: +UE-NR-Capability-v1530 ::= SEQUENCE { + fdd-Add-UE-NR-Capabilities-v1530 UE-NR-CapabilityAddXDD-Mode-v1530 OPTIONAL, + tdd-Add-UE-NR-Capabilities-v1530 UE-NR-CapabilityAddXDD-Mode-v1530 OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + interRAT-Parameters InterRAT-Parameters OPTIONAL, + inactiveState ENUMERATED {supported} OPTIONAL, + delayBudgetReporting ENUMERATED {supported} OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1540 OPTIONAL +} + +UE-NR-Capability-v1540 ::= SEQUENCE { + sdap-Parameters SDAP-Parameters OPTIONAL, + overheatingInd ENUMERATED {supported} OPTIONAL, + ims-Parameters IMS-Parameters OPTIONAL, + fr1-Add-UE-NR-Capabilities-v1540 UE-NR-CapabilityAddFRX-Mode-v1540 OPTIONAL, + fr2-Add-UE-NR-Capabilities-v1540 UE-NR-CapabilityAddFRX-Mode-v1540 OPTIONAL, + fr1-fr2-Add-UE-NR-Capabilities UE-NR-CapabilityAddFRX-Mode OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1550 OPTIONAL +} + +UE-NR-Capability-v1550 ::= SEQUENCE { + reducedCP-Latency ENUMERATED {supported} OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1560 OPTIONAL +} + +UE-NR-Capability-v1560 ::= SEQUENCE { + nrdc-Parameters NRDC-Parameters OPTIONAL, + receivedFilters OCTET STRING (CONTAINING UECapabilityEnquiry-v1560-IEs) OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1570 OPTIONAL +} + +UE-NR-Capability-v1570 ::= SEQUENCE { + nrdc-Parameters-v1570 NRDC-Parameters-v1570 OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1610 OPTIONAL +} + +-- Late non-critical extensions: +UE-NR-Capability-v15c0 ::= SEQUENCE { + nrdc-Parameters-v15c0 NRDC-Parameters-v15c0 OPTIONAL, + partialFR2-FallbackRX-Req ENUMERATED {true} OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- Regular non-critical extensions: +UE-NR-Capability-v1610 ::= SEQUENCE { + inDeviceCoexInd-r16 ENUMERATED {supported} OPTIONAL, + dl-DedicatedMessageSegmentation-r16 ENUMERATED {supported} OPTIONAL, + nrdc-Parameters-v1610 NRDC-Parameters-v1610 OPTIONAL, + powSav-Parameters-r16 PowSav-Parameters-r16 OPTIONAL, + fr1-Add-UE-NR-Capabilities-v1610 UE-NR-CapabilityAddFRX-Mode-v1610 OPTIONAL, + fr2-Add-UE-NR-Capabilities-v1610 UE-NR-CapabilityAddFRX-Mode-v1610 OPTIONAL, + bh-RLF-Indication-r16 ENUMERATED {supported} OPTIONAL, + directSN-AdditionFirstRRC-IAB-r16 ENUMERATED {supported} OPTIONAL, + bap-Parameters-r16 BAP-Parameters-r16 OPTIONAL, + referenceTimeProvision-r16 ENUMERATED {supported} OPTIONAL, + sidelinkParameters-r16 SidelinkParameters-r16 OPTIONAL, + highSpeedParameters-r16 HighSpeedParameters-r16 OPTIONAL, + mac-Parameters-v1610 MAC-Parameters-v1610 OPTIONAL, + mcgRLF-RecoveryViaSCG-r16 ENUMERATED {supported} OPTIONAL, + resumeWithStoredMCG-SCells-r16 ENUMERATED {supported} OPTIONAL, + resumeWithStoredSCG-r16 ENUMERATED {supported} OPTIONAL, + resumeWithSCG-Config-r16 ENUMERATED {supported} OPTIONAL, + ue-BasedPerfMeas-Parameters-r16 UE-BasedPerfMeas-Parameters-r16 OPTIONAL, + son-Parameters-r16 SON-Parameters-r16 OPTIONAL, + onDemandSIB-Connected-r16 ENUMERATED {supported} OPTIONAL, + nonCriticalExtension UE-NR-Capability-v1640 OPTIONAL +} + +UE-NR-Capability-v1640 ::= SEQUENCE { + redirectAtResumeByNAS-r16 ENUMERATED {supported} OPTIONAL, + phy-ParametersSharedSpectrumChAccess-r16 Phy-ParametersSharedSpectrumChAccess-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +UE-NR-CapabilityAddXDD-Mode ::= SEQUENCE { + phy-ParametersXDD-Diff Phy-ParametersXDD-Diff OPTIONAL, + mac-ParametersXDD-Diff MAC-ParametersXDD-Diff OPTIONAL, + measAndMobParametersXDD-Diff MeasAndMobParametersXDD-Diff OPTIONAL +} + +UE-NR-CapabilityAddXDD-Mode-v1530 ::= SEQUENCE { + eutra-ParametersXDD-Diff EUTRA-ParametersXDD-Diff +} + +UE-NR-CapabilityAddFRX-Mode ::= SEQUENCE { + phy-ParametersFRX-Diff Phy-ParametersFRX-Diff OPTIONAL, + measAndMobParametersFRX-Diff MeasAndMobParametersFRX-Diff OPTIONAL +} + +UE-NR-CapabilityAddFRX-Mode-v1540 ::= SEQUENCE { + ims-ParametersFRX-Diff IMS-ParametersFRX-Diff OPTIONAL +} + +UE-NR-CapabilityAddFRX-Mode-v1610 ::= SEQUENCE { + powSav-ParametersFRX-Diff-r16 PowSav-ParametersFRX-Diff-r16 OPTIONAL, + mac-ParametersFRX-Diff-r16 MAC-ParametersFRX-Diff-r16 OPTIONAL +} + +BAP-Parameters-r16 ::= SEQUENCE { + flowControlBH-RLC-ChannelBased-r16 ENUMERATED {supported} OPTIONAL, + flowControlRouting-ID-Based-r16 ENUMERATED {supported} OPTIONAL +} + +-- TAG-UE-NR-CAPABILITY-STOP +-- TAG-SHAREDSPECTRUMCHACCESSPARAMSPERBAND-START + +SharedSpectrumChAccessParamsPerBand-r16 ::= SEQUENCE { + + -- R1 10-1: UL channel access for dynamic channel access mode + ul-DynamicChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-1a: UL channel access for semi-static channel access mode + ul-Semi-StaticChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2: SSB-based RRM for dynamic channel access mode + ssb-RRM-DynamicChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2a: SSB-based RRM for semi-static channel access mode + ssb-RRM-Semi-StaticChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2b: MIB reading on unlicensed cell + mib-Acquisition-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2c: SSB-based RLM for dynamic channel access mode + ssb-RLM-DynamicChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2d: SSB-based RLM for semi-static channel access mode + ssb-RLM-Semi-StaticChAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2e: SIB1 reception on unlicensed cell + sib1-Acquisition-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2f: Support monitoring of extended RAR window + extRA-ResponseWindow-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2g: SSB-based BFD/CBD for dynamic channel access mode + ssb-BFD-CBD-dynamicChannelAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2h: SSB-based BFD/CBD for semi-static channel access mode + ssb-BFD-CBD-semi-staticChannelAccess-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-2i: CSI-RS-based BFD/CBD for NR-U + csi-RS-BFD-CBD-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-7: UL channel access for 10 MHz SCell + ul-ChannelBW-SCell-10mhz-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-10: RSSI and channel occupancy measurement and reporting + rssi-ChannelOccupancyReporting-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-11:SRS starting position at any OFDM symbol in a slot + srs-StartAnyOFDM-Symbol-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-20: Support search space set configuration with freqMonitorLocation-r16 + searchSpaceFreqMonitorLocation-r16 INTEGER (1..5) OPTIONAL, + -- R1 10-20a: Support coreset configuration with rb-Offset + coreset-RB-Offset-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-23:CGI reading on unlicensed cell for ANR functionality + cgi-Acquisition-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-25: Enable configured UL transmissions when DCI 2_0 is configured but not detected + configuredUL-Tx-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-27: Wideband PRACH + prach-Wideband-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-29: Support available RB set indicator field in DCI 2_0 + dci-AvailableRB-Set-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-30: Support channel occupancy duration indicator field in DCI 2_0 + dci-ChOccupancyDuration-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-8: Type B PDSCH length {3, 5, 6, 8, 9, 10, 11, 12, 13} without DMRS shift due to CRS collision + typeB-PDSCH-length-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9: Search space set group switching with explicit DCI 2_0 bit field trigger or with implicit PDCCH decoding with DCI 2_0 monitoring + searchSpaceSetGroupSwitchingwithDCI-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9b: Search space set group switching with implicit PDCCH decoding without DCI 2_0 monitoring FFS:per band or per UE + searchSpaceSetGroupSwitchingwithoutDCI-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-9d: Support Search space set group switching capability 2 + searchSpaceSetGroupSwitchingcapability2-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-14: Non-numerical PDSCH to HARQ-ACK timing + non-numericalPDSCH-HARQ-timing-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-15: Enhanced dynamic HARQ codebook + enhancedDynamicHARQ-codebook-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-16: One-shot HARQ ACK feedback + oneShotHARQ-feedback-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-17: Multi-PUSCH UL grant + multiPUSCH-UL-grant-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-26: CSI-RS based RLM for NR-U + csi-RS-RLM-r16 ENUMERATED {supported} OPTIONAL, + dummy ENUMERATED {supported} OPTIONAL, + -- R1 10-31: Support of P/SP-CSI-RS reception with CSI-RS-ValidationWith-DCI-r16 configured + periodicAndSemi-PersistentCSI-RS-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-3: PRB interlace mapping for PUSCH + pusch-PRB-interlace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-3a: PRB interlace mapping for PUCCH + pucch-F0-F1-PRB-Interlace-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-12: OCC for PRB interlace mapping for PF2 and PF3 + occ-PRB-PF2-PF3-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-13a: Extended CP range of more than one symbol for CG-PUSCH + extCP-rangeCG-PUSCH-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-18: Configured grant with retransmission in CG resources + configuredGrantWithReTx-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-21a: Support using ED threshold given by gNB for UL to DL COT sharing + ed-Threshold-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-21b: Support UL to DL COT sharing + ul-DL-COT-Sharing-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-24: CG-UCI multiplexing with HARQ ACK + mux-CG-UCI-HARQ-ACK-r16 ENUMERATED {supported} OPTIONAL, + -- R1 10-28: Configured grant with Rel-16 enhanced resource configuration + cg-resourceConfig-r16 ENUMERATED {supported} OPTIONAL +} + +SharedSpectrumChAccessParamsPerBand-v1630 ::= SEQUENCE { + -- R4 4-1: DL reception in intra-carrier guardband + dl-ReceptionIntraCellGuardband-r16 ENUMERATED {supported} OPTIONAL, + -- R4 4-2: DL reception when gNB does not transmit on all RB sets of a carrier as a result of LBT + dl-ReceptionLBT-subsetRB-r16 ENUMERATED {supported} OPTIONAL +} + +SharedSpectrumChAccessParamsPerBand-v1640 ::= SEQUENCE { + -- 10-26b(1-4): CSI-RS based RRM measurement with associated SS-block + csi-RSRP-AndRSRQ-MeasWithSSB-r16 ENUMERATED {supported} OPTIONAL, + -- 10-26c(1-5): CSI-RS based RRM measurement without associated SS-block + csi-RSRP-AndRSRQ-MeasWithoutSSB-r16 ENUMERATED {supported} OPTIONAL, + -- 10-26d(1-6): CSI-RS based RS-SINR measurement + csi-SINR-Meas-r16 ENUMERATED {supported} OPTIONAL, + -- 10-26e(1-8): RLM based on a mix of SS block and CSI-RS signals within active BWP + ssb-AndCSI-RS-RLM-r16 ENUMERATED {supported} OPTIONAL, + -- 10-26f(1-9): CSI-RS based contention free RA for HO + csi-RS-CFRA-ForHO-r16 ENUMERATED {supported} OPTIONAL +} +-- TAG-SHAREDSPECTRUMCHACCESSPARAMSPERBAND-STOP +-- TAG-ABSOLUTETIMEINFO-START + +AbsoluteTimeInfo-r16 ::= BIT STRING (SIZE (48)) + +-- TAG-ABSOLUTETIMEINFO-STOP +-- TAG-AREACONFIGURATION-START + +AreaConfiguration-r16 ::= SEQUENCE { + areaConfig-r16 AreaConfig-r16, + interFreqTargetList-r16 SEQUENCE(SIZE (1..maxFreq)) OF InterFreqTargetInfo-r16 OPTIONAL -- Need R +} + +AreaConfig-r16 ::= CHOICE { + cellGlobalIdList-r16 CellGlobalIdList-r16, + trackingAreaCodeList-r16 TrackingAreaCodeList-r16, + trackingAreaIdentityList-r16 TrackingAreaIdentityList-r16 +} + +InterFreqTargetInfo-r16 ::= SEQUENCE { + dl-CarrierFreq ARFCN-ValueNR, + cellList SEQUENCE (SIZE (1..32)) OF PhysCellId OPTIONAL +} + +CellGlobalIdList-r16 ::= SEQUENCE (SIZE (1..32)) OF CGI-Info-Logging-r16 + +TrackingAreaCodeList-r16 ::= SEQUENCE (SIZE (1..8)) OF TrackingAreaCode + +TrackingAreaIdentityList-r16 ::= SEQUENCE (SIZE (1..8)) OF TrackingAreaIdentity-r16 + +TrackingAreaIdentity-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + trackingAreaCode-r16 TrackingAreaCode +} + +-- TAG-AREACONFIGURATION-STOP +-- TAG-BTNAMELIST-START + +BT-NameList-r16 ::= SEQUENCE (SIZE (1..maxBT-Name-r16)) OF BT-Name-r16 + +BT-Name-r16 ::= OCTET STRING (SIZE (1..248)) + +-- TAG-BTNAMELIST-STOP +-- TAG-EUTRA-ALLOWEDMEASBANDWIDTH-START + +EUTRA-AllowedMeasBandwidth ::= ENUMERATED {mbw6, mbw15, mbw25, mbw50, mbw75, mbw100} + +-- TAG-EUTRA-ALLOWEDMEASBANDWIDTH-STOP +-- TAG-EUTRA-MBSFN-SUBFRAMECONFIGLIST-START + +EUTRA-MBSFN-SubframeConfigList ::= SEQUENCE (SIZE (1..maxMBSFN-Allocations)) OF EUTRA-MBSFN-SubframeConfig + +EUTRA-MBSFN-SubframeConfig ::= SEQUENCE { + radioframeAllocationPeriod ENUMERATED {n1, n2, n4, n8, n16, n32}, + radioframeAllocationOffset INTEGER (0..7), + subframeAllocation1 CHOICE { + oneFrame BIT STRING (SIZE(6)), + fourFrames BIT STRING (SIZE(24)) + }, + subframeAllocation2 CHOICE { + oneFrame BIT STRING (SIZE(2)), + fourFrames BIT STRING (SIZE(8)) + } OPTIONAL, -- Need R + ... +} + +-- TAG-EUTRA-MBSFN-SUBFRAMECONFIGLIST-STOP +-- TAG-EUTRA-MULTIBANDINFOLIST-START + +EUTRA-MultiBandInfoList ::= SEQUENCE (SIZE (1..maxMultiBands)) OF EUTRA-MultiBandInfo + +EUTRA-MultiBandInfo ::= SEQUENCE { + eutra-FreqBandIndicator FreqBandIndicatorEUTRA, + eutra-NS-PmaxList EUTRA-NS-PmaxList OPTIONAL -- Need R +} + +-- TAG-EUTRA-MULTIBANDINFOLIST-STOP +-- TAG-EUTRA-NS-PMAXLIST-START + +EUTRA-NS-PmaxList ::= SEQUENCE (SIZE (1..maxEUTRA-NS-Pmax)) OF EUTRA-NS-PmaxValue + +EUTRA-NS-PmaxValue ::= SEQUENCE { + additionalPmax INTEGER (-30..33) OPTIONAL, -- Need R + additionalSpectrumEmission INTEGER (1..288) OPTIONAL -- Need R +} + +-- TAG-EUTRA-NS-PMAXLIST-STOP +-- TAG-EUTRA-PHYSCELLID-START + +EUTRA-PhysCellId ::= INTEGER (0..503) + +-- TAG-EUTRA-PHYSCELLID-STOP +-- TAG-EUTRA-PHYSCELLIDRANGE-START + +EUTRA-PhysCellIdRange ::= SEQUENCE { + start EUTRA-PhysCellId, + range ENUMERATED {n4, n8, n12, n16, n24, n32, n48, n64, n84, n96, + n128, n168, n252, n504, spare2, spare1} OPTIONAL -- Need N +} + +-- TAG-EUTRA-PHYSCELLIDRANGE-STOP +-- TAG-EUTRA-PRESENCEANTENNAPORT1-START + +EUTRA-PresenceAntennaPort1 ::= BOOLEAN + +-- TAG-EUTRA-PRESENCEANTENNAPORT1-STOP +-- TAG-EUTRA-Q-OFFSETRANGE-START + +EUTRA-Q-OffsetRange ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-EUTRA-Q-OFFSETRANGE-STOP +-- TAG-IABIPADDRESS-START + +IAB-IP-Address-r16 ::= CHOICE { + iPv4-Address-r16 BIT STRING (SIZE(32)), + iPv6-Address-r16 BIT STRING (SIZE(128)), + iPv6-Prefix-r16 BIT STRING (SIZE(64)), + ... +} + +-- TAG-IABIPADDRESS-STOP +-- TAG-IABIPADDRESSINDEX-START + +IAB-IP-AddressIndex-r16 ::= INTEGER (1..maxIAB-IP-Address-r16) + +-- TAG-IABIPADDRESSINDEX-STOP +-- TAG-IAB-IP-USAGE-START + +IAB-IP-Usage-r16 ::= ENUMERATED {f1-C, f1-U, non-F1, spare} + +-- TAG-IAB-IP-USAGE-STOP +-- TAG-LOGGINGDURATION-START + +LoggingDuration-r16 ::= ENUMERATED { + min10, min20, min40, min60, min90, min120, spare2, spare1} + +-- TAG-LOGGINGDURATION-STOP +-- TAG-LOGGINGINTERVAL-START + +LoggingInterval-r16 ::= ENUMERATED { + ms320, ms640, ms1280, ms2560, ms5120, ms10240, ms20480, + ms30720, ms40960, ms61440 , infinity} + +-- TAG-LOGGINGINTERVAL-STOP +-- TAG-LOGMEASRESULTLISTBT-START + +LogMeasResultListBT-r16 ::= SEQUENCE (SIZE (1..maxBT-IdReport-r16)) OF LogMeasResultBT-r16 + +LogMeasResultBT-r16 ::= SEQUENCE { + bt-Addr-r16 BIT STRING (SIZE (48)), + rssi-BT-r16 INTEGER (-128..127) OPTIONAL, + ... +} + +-- TAG-LOGMEASRESULTLISTBT-STOP +-- TAG-LOGMEASRESULTLISTWLAN-START + +LogMeasResultListWLAN-r16 ::= SEQUENCE (SIZE (1..maxWLAN-Id-Report-r16)) OF LogMeasResultWLAN-r16 + +LogMeasResultWLAN-r16 ::= SEQUENCE { + wlan-Identifiers-r16 WLAN-Identifiers-r16, + rssiWLAN-r16 WLAN-RSSI-Range-r16 OPTIONAL, + rtt-WLAN-r16 WLAN-RTT-r16 OPTIONAL, + ... +} + +WLAN-Identifiers-r16 ::= SEQUENCE { + ssid-r16 OCTET STRING (SIZE (1..32)) OPTIONAL, + bssid-r16 OCTET STRING (SIZE (6)) OPTIONAL, + hessid-r16 OCTET STRING (SIZE (6)) OPTIONAL, + ... +} + +WLAN-RSSI-Range-r16 ::= INTEGER(0..141) + +WLAN-RTT-r16 ::= SEQUENCE { + rttValue-r16 INTEGER (0..16777215), + rttUnits-r16 ENUMERATED { + microseconds, + hundredsofnanoseconds, + tensofnanoseconds, + nanoseconds, + tenthsofnanoseconds, + ...}, + rttAccuracy-r16 INTEGER (0..255) OPTIONAL, + ... +} + +-- TAG-OTHERCONFIG-START + +OtherConfig ::= SEQUENCE { + delayBudgetReportingConfig CHOICE{ + release NULL, + setup SEQUENCE{ + delayBudgetReportingProhibitTimer ENUMERATED {s0, s0dot4, s0dot8, s1dot6, s3, s6, s12, s30} + } + } OPTIONAL -- Need M +} + +OtherConfig-v1540 ::= SEQUENCE { + overheatingAssistanceConfig SetupRelease {OverheatingAssistanceConfig} OPTIONAL, -- Need M + ... +} +CandidateServingFreqListNR-r16 ::= SEQUENCE (SIZE (1..maxFreqIDC-r16)) OF ARFCN-ValueNR + +OtherConfig-v1610 ::= SEQUENCE { + idc-AssistanceConfig-r16 SetupRelease {IDC-AssistanceConfig-r16} OPTIONAL, -- Need M + drx-PreferenceConfig-r16 SetupRelease {DRX-PreferenceConfig-r16} OPTIONAL, -- Need M + maxBW-PreferenceConfig-r16 SetupRelease {MaxBW-PreferenceConfig-r16} OPTIONAL, -- Need M + maxCC-PreferenceConfig-r16 SetupRelease {MaxCC-PreferenceConfig-r16} OPTIONAL, -- Need M + maxMIMO-LayerPreferenceConfig-r16 SetupRelease {MaxMIMO-LayerPreferenceConfig-r16} OPTIONAL, -- Need M + minSchedulingOffsetPreferenceConfig-r16 SetupRelease {MinSchedulingOffsetPreferenceConfig-r16} OPTIONAL, -- Need M + releasePreferenceConfig-r16 SetupRelease {ReleasePreferenceConfig-r16} OPTIONAL, -- Need M + referenceTimePreferenceReporting-r16 ENUMERATED {true} OPTIONAL, -- Need R + btNameList-r16 SetupRelease {BT-NameList-r16} OPTIONAL, -- Need M + wlanNameList-r16 SetupRelease {WLAN-NameList-r16} OPTIONAL, -- Need M + sensorNameList-r16 SetupRelease {Sensor-NameList-r16} OPTIONAL, -- Need M + obtainCommonLocation-r16 ENUMERATED {true} OPTIONAL, -- Need R + sl-AssistanceConfigNR-r16 ENUMERATED{true} OPTIONAL -- Need R +} + +OverheatingAssistanceConfig ::= SEQUENCE { + overheatingIndicationProhibitTimer ENUMERATED {s0, s0dot5, s1, s2, s5, s10, s20, s30, + s60, s90, s120, s300, s600, spare3, spare2, spare1} +} + +IDC-AssistanceConfig-r16 ::= SEQUENCE { + candidateServingFreqListNR-r16 CandidateServingFreqListNR-r16 OPTIONAL, -- Need R + ... +} + +DRX-PreferenceConfig-r16 ::= SEQUENCE { + drx-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxBW-PreferenceConfig-r16 ::= SEQUENCE { + maxBW-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxCC-PreferenceConfig-r16 ::= SEQUENCE { + maxCC-PreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MaxMIMO-LayerPreferenceConfig-r16 ::= SEQUENCE { + maxMIMO-LayerPreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +MinSchedulingOffsetPreferenceConfig-r16 ::= SEQUENCE { + minSchedulingOffsetPreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, spare2, spare1} +} + +ReleasePreferenceConfig-r16 ::= SEQUENCE { + releasePreferenceProhibitTimer-r16 ENUMERATED { + s0, s0dot5, s1, s2, s3, s4, s5, s6, s7, + s8, s9, s10, s20, s30, infinity, spare1}, + connectedReporting ENUMERATED {true} OPTIONAL -- Need R +} + +-- TAG-OTHERCONFIG-STOP +-- TAG-PHYSCELLIDUTRA-FDD-START + +PhysCellIdUTRA-FDD-r16 ::= INTEGER (0..511) + +-- TAG-PHYSCELLIDUTRA-FDD-STOP +-- TAG-RRC-TRANSACTIONIDENTIFIER-START + +RRC-TransactionIdentifier ::= INTEGER (0..3) + +-- TAG-RRC-TRANSACTIONIDENTIFIER-STOP +-- TAG-SENSORNAMELIST-START + +Sensor-NameList-r16 ::= SEQUENCE { + measUncomBarPre-r16 ENUMERATED {true} OPTIONAL, -- Need R + measUeSpeed ENUMERATED {true} OPTIONAL, -- Need R + measUeOrientation ENUMERATED {true} OPTIONAL -- Need R +} + +-- TAG-SENSORNAMELIST-STOP +-- TAG-TRACEREFERENCE-START + +TraceReference-r16 ::= SEQUENCE { + plmn-Identity-r16 PLMN-Identity, + traceId-r16 OCTET STRING (SIZE (3)) +} + +-- TAG-TRACEREFERENCE-STOP +-- TAG-UE-MeasurementsAvailable-START + +UE-MeasurementsAvailable-r16 ::= SEQUENCE { + logMeasAvailable-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableBT-r16 ENUMERATED {true} OPTIONAL, + logMeasAvailableWLAN-r16 ENUMERATED {true} OPTIONAL, + connEstFailInfoAvailable-r16 ENUMERATED {true} OPTIONAL, + rlf-InfoAvailable-r16 ENUMERATED {true} OPTIONAL, + ... +} + +-- TAG-UE-MeasurementsAvailable-STOP +-- TAG-UTRA-FDD-Q-OFFSETRANGE-START + +UTRA-FDD-Q-OffsetRange-r16 ::= ENUMERATED { + dB-24, dB-22, dB-20, dB-18, dB-16, dB-14, + dB-12, dB-10, dB-8, dB-6, dB-5, dB-4, dB-3, + dB-2, dB-1, dB0, dB1, dB2, dB3, dB4, dB5, + dB6, dB8, dB10, dB12, dB14, dB16, dB18, + dB20, dB22, dB24} + +-- TAG-UTRA-FDD-Q-OFFSETRANGE-STOP +-- TAG-VISITEDCELLINFOLIST-START + +VisitedCellInfoList-r16 ::= SEQUENCE (SIZE (1..maxCellHistory-r16)) OF VisitedCellInfo-r16 + +VisitedCellInfo-r16 ::= SEQUENCE { + visitedCellId-r16 CHOICE { + nr-CellId-r16 CHOICE { + cgi-Info CGI-Info-Logging-r16, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 PhysCellId, + carrierFreq-r16 ARFCN-ValueNR + } + }, + eutra-CellId-r16 CHOICE { + cellGlobalId-r16 CGI-InfoEUTRA, + pci-arfcn-r16 SEQUENCE { + physCellId-r16 EUTRA-PhysCellId, + carrierFreq-r16 ARFCN-ValueEUTRA + } + } + } OPTIONAL, + timeSpent-r16 INTEGER (0..4095), + ... +} + +-- TAG-VISITEDCELLINFOLIST-STOP +-- TAG-WLANNAMELIST-START + +WLAN-NameList-r16 ::= SEQUENCE (SIZE (1..maxWLAN-Name-r16)) OF WLAN-Name-r16 + +WLAN-Name-r16 ::= OCTET STRING (SIZE (1..32)) + +-- TAG-SL-BWP-CONFIG-START + +SL-BWP-Config-r16 ::= SEQUENCE { + sl-BWP-Id BWP-Id, + sl-BWP-Generic-r16 SL-BWP-Generic-r16 OPTIONAL, -- Need M + sl-BWP-PoolConfig-r16 SL-BWP-PoolConfig-r16 OPTIONAL, -- Need M + ... +} + +SL-BWP-Generic-r16 ::= SEQUENCE { + sl-BWP-r16 BWP OPTIONAL, -- Need M + sl-LengthSymbols-r16 ENUMERATED {sym7, sym8, sym9, sym10, sym11, sym12, sym13, sym14} OPTIONAL, -- Need M + sl-StartSymbol-r16 ENUMERATED {sym0, sym1, sym2, sym3, sym4, sym5, sym6, sym7} OPTIONAL, -- Need M + sl-PSBCH-Config-r16 SetupRelease {SL-PSBCH-Config-r16} OPTIONAL, -- Need M + sl-TxDirectCurrentLocation-r16 INTEGER (0..3301) OPTIONAL, -- Need M + ... +} + +-- TAG-SL-BWP-CONFIG-STOP +-- TAG-SL-BWP-CONFIGCOMMON-START + +SL-BWP-ConfigCommon-r16 ::= SEQUENCE { + sl-BWP-Generic-r16 SL-BWP-Generic-r16 OPTIONAL, -- Need R + sl-BWP-PoolConfigCommon-r16 SL-BWP-PoolConfigCommon-r16 OPTIONAL, -- Need R + ... +} + +-- TAG-SL-BWP-CONFIGCOMMON-STOP +-- TAG-SL-BWP-POOLCONFIG-START + +SL-BWP-PoolConfig-r16 ::= SEQUENCE { + sl-RxPool-r16 SEQUENCE (SIZE (1..maxNrofRXPool-r16)) OF SL-ResourcePool-r16 OPTIONAL, -- Cond HO + sl-TxPoolSelectedNormal-r16 SL-TxPoolDedicated-r16 OPTIONAL, -- Need M + sl-TxPoolScheduling-r16 SL-TxPoolDedicated-r16 OPTIONAL, -- Need N + sl-TxPoolExceptional-r16 SL-ResourcePoolConfig-r16 OPTIONAL -- Need M +} + +SL-TxPoolDedicated-r16 ::= SEQUENCE { + sl-PoolToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolID-r16 OPTIONAL, -- Need N + sl-PoolToAddModList-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolConfig-r16 OPTIONAL -- Need N +} + +SL-ResourcePoolConfig-r16 ::= SEQUENCE { + sl-ResourcePoolID-r16 SL-ResourcePoolID-r16, + sl-ResourcePool-r16 SL-ResourcePool-r16 OPTIONAL -- Need M +} + +SL-ResourcePoolID-r16 ::= INTEGER (1..maxNrofPoolID-r16) + +-- TAG-SL-BWP-POOLCONFIG-STOP +-- TAG-SL-BWP-POOLCONFIGCOMMON-START + +SL-BWP-PoolConfigCommon-r16 ::= SEQUENCE { + sl-RxPool-r16 SEQUENCE (SIZE (1..maxNrofRXPool-r16)) OF SL-ResourcePool-r16 OPTIONAL, -- Need R + sl-TxPoolSelectedNormal-r16 SEQUENCE (SIZE (1..maxNrofTXPool-r16)) OF SL-ResourcePoolConfig-r16 OPTIONAL, -- Need R + sl-TxPoolExceptional-r16 SL-ResourcePoolConfig-r16 OPTIONAL -- Need R +} + +-- TAG-SL-BWP-POOLCONFIGCOMMON-STOP +-- TAG-SL-CBR-PRIORITYTXCONFIGLIST-START + +SL-CBR-PriorityTxConfigList-r16 ::= SEQUENCE (SIZE (1..8)) OF SL-PriorityTxConfigIndex-r16 + +SL-PriorityTxConfigIndex-r16 ::= SEQUENCE { + sl-PriorityThreshold-r16 INTEGER (1..8) OPTIONAL, -- Need M + sl-DefaultTxConfigIndex-r16 INTEGER (0..maxCBR-Level-1-r16) OPTIONAL, -- Need M + sl-CBR-ConfigIndex-r16 INTEGER (0..maxCBR-Config-1-r16) OPTIONAL, -- Need M + sl-Tx-ConfigIndexList-r16 SEQUENCE (SIZE (1.. maxCBR-Level-r16)) OF SL-TxConfigIndex-r16 OPTIONAL -- Need M +} + +SL-TxConfigIndex-r16 ::= INTEGER (0..maxTxConfig-1-r16) + +-- TAG-SL-CBR-PRIORITYTXCONFIGLIST-STOP +-- TAG-SL-CBR-COMMONTXCONFIGLIST-START + +SL-CBR-CommonTxConfigList-r16 ::= SEQUENCE { + sl-CBR-RangeConfigList-r16 SEQUENCE (SIZE (1..maxCBR-Config-r16)) OF SL-CBR-LevelsConfig-r16 OPTIONAL, -- Need M + sl-CBR-PSSCH-TxConfigList-r16 SEQUENCE (SIZE (1.. maxTxConfig-r16)) OF SL-CBR-PSSCH-TxConfig-r16 OPTIONAL -- Need M +} + +SL-CBR-LevelsConfig-r16 ::= SEQUENCE (SIZE (1..maxCBR-Level-r16)) OF SL-CBR-r16 + +SL-CBR-PSSCH-TxConfig-r16 ::= SEQUENCE { + sl-CR-Limit-r16 INTEGER(0..10000) OPTIONAL, -- Need M + sl-TxParameters-r16 SL-PSSCH-TxParameters-r16 OPTIONAL -- Need M +} + +SL-CBR-r16 ::= INTEGER (0..100) + +-- TAG-SL-CBR-COMMONTXCONFIGLIST-STOP +-- TAG-SL-CONFIGDEDICATEDNR-START + +SL-ConfigDedicatedNR-r16 ::= SEQUENCE { + sl-PHY-MAC-RLC-Config-r16 SL-PHY-MAC-RLC-Config-r16 OPTIONAL, -- Need M + sl-RadioBearerToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SLRB-Uu-ConfigIndex-r16 OPTIONAL, -- Need N + sl-RadioBearerToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SL-RadioBearerConfig-r16 OPTIONAL, -- Need N + sl-MeasConfigInfoToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-DestinationIndex-r16 OPTIONAL, -- Need N + sl-MeasConfigInfoToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSL-Dest-r16)) OF SL-MeasConfigInfo-r16 OPTIONAL, -- Need M + t400-r16 ENUMERATED {ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000} OPTIONAL, -- Need M + ... +} + +SL-DestinationIndex-r16 ::= INTEGER (0..maxNrofSL-Dest-1-r16) + +SL-PHY-MAC-RLC-Config-r16::= SEQUENCE { + sl-ScheduledConfig-r16 SetupRelease { SL-ScheduledConfig-r16 } OPTIONAL, -- Need M + sl-UE-SelectedConfig-r16 SetupRelease { SL-UE-SelectedConfig-r16 } OPTIONAL, -- Need M + sl-FreqInfoToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-Freq-Id-r16 OPTIONAL, -- Need N + sl-FreqInfoToAddModList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-FreqConfig-r16 OPTIONAL, -- Need N + sl-RLC-BearerToReleaseList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfigIndex-r16 OPTIONAL, -- Need N + sl-RLC-BearerToAddModList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfig-r16 OPTIONAL, -- Need N + sl-MaxNumConsecutiveDTX-r16 ENUMERATED {n1, n2, n3, n4, n6, n8, n16, n32} OPTIONAL, -- Need M + sl-CSI-Acquisition-r16 ENUMERATED {enabled} OPTIONAL, -- Need R + sl-CSI-SchedulingRequestId-r16 SetupRelease {SchedulingRequestId} OPTIONAL, -- Need M + sl-SSB-PriorityNR-r16 INTEGER (1..8) OPTIONAL, -- Need R + networkControlledSyncTx-r16 ENUMERATED {on, off} OPTIONAL -- Need M +} + +-- TAG-SL-CONFIGDEDICATEDNR-STOP +-- TAG-SL-CONFIGUREDGRANTCONFIG-START + +SL-ConfiguredGrantConfig-r16 ::= SEQUENCE { + sl-ConfigIndexCG-r16 SL-ConfigIndexCG-r16, + sl-PeriodCG-r16 SL-PeriodCG-r16 OPTIONAL, -- Need M + sl-NrOfHARQ-Processes-r16 INTEGER (1..16) OPTIONAL, -- Need M + sl-HARQ-ProcID-offset-r16 INTEGER (0..15) OPTIONAL, -- Need M + sl-CG-MaxTransNumList-r16 SL-CG-MaxTransNumList-r16 OPTIONAL, -- Need M + rrc-ConfiguredSidelinkGrant-r16 SEQUENCE { + sl-TimeResourceCG-Type1-r16 INTEGER (0..496) OPTIONAL, -- Need M + sl-StartSubchannelCG-Type1-r16 INTEGER (0..26) OPTIONAL, -- Need M + sl-FreqResourceCG-Type1-r16 INTEGER (0..6929) OPTIONAL, -- Need M + sl-TimeOffsetCG-Type1-r16 INTEGER (0..7999) OPTIONAL, -- Need R + sl-N1PUCCH-AN-r16 PUCCH-ResourceId OPTIONAL, -- Need M + sl-PSFCH-ToPUCCH-CG-Type1-r16 INTEGER (0..15) OPTIONAL, -- Need M + sl-ResourcePoolID-r16 SL-ResourcePoolID-r16 OPTIONAL, -- Need M + sl-TimeReferenceSFN-Type1-r16 ENUMERATED {sfn512} OPTIONAL -- Need S + } OPTIONAL, -- Need M + ... +} + +SL-ConfigIndexCG-r16 ::= INTEGER (0..maxNrofCG-SL-r16-1) + +SL-CG-MaxTransNumList-r16 ::= SEQUENCE (SIZE (1..8)) OF SL-CG-MaxTransNum-r16 + +SL-CG-MaxTransNum-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-MaxTransNum-r16 INTEGER (1..32) +} + +SL-PeriodCG-r16 ::= CHOICE{ + sl-PeriodCG1-r16 ENUMERATED {ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000, spare6, + spare5, spare4, spare3, spare2, spare1}, + sl-PeriodCG2-r16 INTEGER (1..99) +} + +-- TAG-SL-CONFIGUREDGRANTCONFIG-STOP +-- TAG-SL-DESTINATIONIDENTITY-START + +SL-DestinationIdentity-r16 ::= BIT STRING (SIZE (24)) + +-- TAG-SL-DESTINATIONIDENTITY-STOP +-- TAG-SL-FREQCONFIG-START + +SL-FreqConfig-r16 ::= SEQUENCE { + sl-Freq-Id-r16 SL-Freq-Id-r16, + sl-SCS-SpecificCarrierList-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + sl-AbsoluteFrequencyPointA-r16 ARFCN-ValueNR OPTIONAL, -- Need M + sl-AbsoluteFrequencySSB-r16 ARFCN-ValueNR OPTIONAL, -- Need R + frequencyShift7p5khzSL-r16 ENUMERATED {true} OPTIONAL, -- Cond V2X-SL-Shared + valueN-r16 INTEGER (-1..1), + sl-BWP-ToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF BWP-Id OPTIONAL, -- Need N + sl-BWP-ToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF SL-BWP-Config-r16 OPTIONAL, -- Need N + sl-SyncConfigList-r16 SL-SyncConfigList-r16 OPTIONAL, -- Need M + sl-SyncPriority-r16 ENUMERATED {gnss, gnbEnb} OPTIONAL -- Need M +} + +SL-Freq-Id-r16 ::= INTEGER (1.. maxNrofFreqSL-r16) + +-- TAG-SL-FREQCONFIG-STOP +-- TAG-SL-FREQCONFIGCOMMON-START + +SL-FreqConfigCommon-r16 ::= SEQUENCE { + sl-SCS-SpecificCarrierList-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SCS-SpecificCarrier, + sl-AbsoluteFrequencyPointA-r16 ARFCN-ValueNR, + sl-AbsoluteFrequencySSB-r16 ARFCN-ValueNR OPTIONAL, -- Need R + frequencyShift7p5khzSL-r16 ENUMERATED {true} OPTIONAL, -- Cond V2X-SL-Shared + valueN-r16 INTEGER (-1..1), + sl-BWP-List-r16 SEQUENCE (SIZE (1..maxNrofSL-BWPs-r16)) OF SL-BWP-ConfigCommon-r16 OPTIONAL, -- Need R + sl-SyncPriority-r16 ENUMERATED {gnss, gnbEnb} OPTIONAL, -- Need R + sl-NbAsSync-r16 BOOLEAN OPTIONAL, -- Need R + sl-SyncConfigList-r16 SL-SyncConfigList-r16 OPTIONAL, -- Need R + ... +} +-- TAG-SL-FREQCONFIGCOMMON-STOP +-- TAG-SL-LOGICALCHANNELCONFIG-START + +SL-LogicalChannelConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-PrioritisedBitRate-r16 ENUMERATED {kBps0, kBps8, kBps16, kBps32, kBps64, kBps128, kBps256, kBps512, + kBps1024, kBps2048, kBps4096, kBps8192, kBps16384, kBps32768, kBps65536, infinity}, + sl-BucketSizeDuration-r16 ENUMERATED {ms5, ms10, ms20, ms50, ms100, ms150, ms300, ms500, ms1000, + spare7, spare6, spare5, spare4, spare3,spare2, spare1}, + sl-ConfiguredGrantType1Allowed-r16 ENUMERATED {true} OPTIONAL, -- Need R + sl-HARQ-FeedbackEnabled-r16 ENUMERATED {enabled, disabled } OPTIONAL, -- Need R + sl-AllowedCG-List-r16 SEQUENCE (SIZE (0.. maxNrofCG-SL-r16-1)) OF SL-ConfigIndexCG-r16 + OPTIONAL, -- Need R + sl-AllowedSCS-List-r16 SEQUENCE (SIZE (1..maxSCSs)) OF SubcarrierSpacing OPTIONAL, -- Need R + sl-MaxPUSCH-Duration-r16 ENUMERATED {ms0p02, ms0p04, ms0p0625, ms0p125, ms0p25, ms0p5, spare2, spare1} + OPTIONAL, -- Need R + sl-LogicalChannelGroup-r16 INTEGER (0..maxLCG-ID) OPTIONAL, -- Need R + sl-SchedulingRequestId-r16 SchedulingRequestId OPTIONAL, -- Need R + sl-LogicalChannelSR-DelayTimerApplied-r16 BOOLEAN OPTIONAL, -- Need R + ... +} +-- TAG-SL-LOGICALCHANNELCONFIG-STOP +-- TAG-SL-MEASCONFIGCOMMON-START + +SL-MeasConfigCommon-r16 ::= SEQUENCE { + sl-MeasObjectListCommon-r16 SL-MeasObjectList-r16 OPTIONAL, -- Need R + sl-ReportConfigListCommon-r16 SL-ReportConfigList-r16 OPTIONAL, -- Need R + sl-MeasIdListCommon-r16 SL-MeasIdList-r16 OPTIONAL, -- Need R + sl-QuantityConfigCommon-r16 SL-QuantityConfig-r16 OPTIONAL, -- Need R + ... +} + +-- TAG-SL-MEASCONFIGCOMMON-STOP +-- TAG-SL-MEASCONFIGINFO-START + +SL-MeasConfigInfo-r16 ::= SEQUENCE { + sl-DestinationIndex-r16 SL-DestinationIndex-r16, + sl-MeasConfig-r16 SL-MeasConfig-r16, + ... +} + +SL-MeasConfig-r16 ::= SEQUENCE { + sl-MeasObjectToRemoveList-r16 SL-MeasObjectToRemoveList-r16 OPTIONAL, -- Need N + sl-MeasObjectToAddModList-r16 SL-MeasObjectList-r16 OPTIONAL, -- Need N + sl-ReportConfigToRemoveList-r16 SL-ReportConfigToRemoveList-r16 OPTIONAL, -- Need N + sl-ReportConfigToAddModList-r16 SL-ReportConfigList-r16 OPTIONAL, -- Need N + sl-MeasIdToRemoveList-r16 SL-MeasIdToRemoveList-r16 OPTIONAL, -- Need N + sl-MeasIdToAddModList-r16 SL-MeasIdList-r16 OPTIONAL, -- Need N + sl-QuantityConfig-r16 SL-QuantityConfig-r16 OPTIONAL, -- Need M + ... +} + +SL-MeasObjectToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ObjectId-r16)) OF SL-MeasObjectId-r16 + +SL-ReportConfigToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ReportConfigId-r16)) OF SL-ReportConfigId-r16 + +SL-MeasIdToRemoveList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF SL-MeasId-r16 + +-- TAG-SL-MEASCONFIGINFO-STOP +-- TAG-SL-MEASIDLIST-START + +SL-MeasIdList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF SL-MeasIdInfo-r16 + +SL-MeasIdInfo-r16 ::= SEQUENCE { + sl-MeasId-r16 SL-MeasId-r16, + sl-MeasObjectId-r16 SL-MeasObjectId-r16, + sl-ReportConfigId-r16 SL-ReportConfigId-r16, + ... +} + +SL-MeasId-r16 ::= INTEGER (1..maxNrofSL-MeasId-r16) + +-- TAG-SL-MEASIDLIST-STOP +-- TAG-SL-MEASOBJECTLIST-START + +SL-MeasObjectList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ObjectId-r16)) OF SL-MeasObjectInfo-r16 + +SL-MeasObjectInfo-r16 ::= SEQUENCE { + sl-MeasObjectId-r16 SL-MeasObjectId-r16, + sl-MeasObject-r16 SL-MeasObject-r16, + ... +} + +SL-MeasObjectId-r16 ::= INTEGER (1..maxNrofSL-ObjectId-r16) + +SL-MeasObject-r16 ::= SEQUENCE { + frequencyInfoSL-r16 ARFCN-ValueNR, + ... +} + +-- TAG-SL-MEASOBJECTLIST-STOP +-- TAG-SL-PDCP-CONFIG-START + +SL-PDCP-Config-r16 ::= SEQUENCE { + sl-DiscardTimer-r16 ENUMERATED {ms3, ms10, ms20, ms25, ms30, ms40, ms50, ms60, ms75, ms100, ms150, ms200, + ms250, ms300, ms500, ms750, ms1500, infinity} OPTIONAL, -- Cond Setup + sl-PDCP-SN-Size-r16 ENUMERATED {len12bits, len18bits} OPTIONAL, -- Cond Setup2 + sl-OutOfOrderDelivery ENUMERATED { true } OPTIONAL, -- Need R + ... +} + +-- TAG-SL-PDCP-CONFIG-STOP +-- TAG-SL-PSBCH-CONFIG-START + +SL-PSBCH-Config-r16 ::= SEQUENCE { + dl-P0-PSBCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + dl-Alpha-PSBCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need M + ... +} + +-- TAG-SL-PSBCH-CONFIG-STOP +-- TAG-SL-PSSCH-TXCONFIGLIST-START + +SL-PSSCH-TxConfigList-r16 ::= SEQUENCE (SIZE (1..maxPSSCH-TxConfig-r16)) OF SL-PSSCH-TxConfig-r16 + +SL-PSSCH-TxConfig-r16 ::= SEQUENCE { + sl-TypeTxSync-r16 SL-TypeTxSync-r16 OPTIONAL, -- Need R + sl-ThresUE-Speed-r16 ENUMERATED {kmph60, kmph80, kmph100, kmph120, + kmph140, kmph160, kmph180, kmph200}, + sl-ParametersAboveThres-r16 SL-PSSCH-TxParameters-r16, + sl-ParametersBelowThres-r16 SL-PSSCH-TxParameters-r16, + ... +} + + +SL-PSSCH-TxParameters-r16 ::= SEQUENCE { + sl-MinMCS-PSSCH-r16 INTEGER (0..27), + sl-MaxMCS-PSSCH-r16 INTEGER (0..31), + sl-MinSubChannelNumPSSCH-r16 INTEGER (1..27), + sl-MaxSubchannelNumPSSCH-r16 INTEGER (1..27), + sl-MaxTxTransNumPSSCH-r16 INTEGER (1..32), + sl-MaxTxPower-r16 SL-TxPower-r16 OPTIONAL -- Cond CBR +} + +-- TAG-SL-PSSCH-TXCONFIGLIST-STOP +-- TAG-SL-QOS-FLOWIDENTITY-START + +SL-QoS-FlowIdentity-r16 ::= INTEGER (1..maxNrofSL-QFIs-r16) + +-- TAG-SL-QOS-FLOWIDENTITY-STOP +-- TAG-SL-QOS-PROFILE-START + +SL-QoS-Profile-r16 ::= SEQUENCE { + sl-PQI-r16 SL-PQI-r16 OPTIONAL, -- Need R + sl-GFBR-r16 INTEGER (0..4000000000) OPTIONAL, -- Need R + sl-MFBR-r16 INTEGER (0..4000000000) OPTIONAL, -- Need R + sl-Range-r16 INTEGER (1..1000) OPTIONAL, -- Need R + ... +} + +SL-PQI-r16 ::= CHOICE { + sl-StandardizedPQI-r16 INTEGER (0..255), + sl-Non-StandardizedPQI-r16 SEQUENCE { + sl-ResourceType-r16 ENUMERATED {gbr, non-GBR, delayCriticalGBR, spare1} OPTIONAL, -- Need R + sl-PriorityLevel-r16 INTEGER (1..8) OPTIONAL, -- Need R + sl-PacketDelayBudget-r16 INTEGER (0..1023) OPTIONAL, -- Need R + sl-PacketErrorRate-r16 INTEGER (0..9) OPTIONAL, -- Need R + sl-AveragingWindow-r16 INTEGER (0..4095) OPTIONAL, -- Need R + sl-MaxDataBurstVolume-r16 INTEGER (0..4095) OPTIONAL, -- Need R + ... + } +} + +-- TAG-SL-QOS-PROFILE-STOP +-- TAG-SL-QUANTITYCONFIG-START + +SL-QuantityConfig-r16 ::= SEQUENCE { + sl-FilterCoefficientDMRS-r16 FilterCoefficient DEFAULT fc4, + ... +} + +-- TAG-SL-QuantityConfig-STOP +-- TAG-SL-RADIOBEARERCONFIG-START + +SL-RadioBearerConfig-r16 ::= SEQUENCE { + slrb-Uu-ConfigIndex-r16 SLRB-Uu-ConfigIndex-r16, + sl-SDAP-Config-r16 SL-SDAP-Config-r16 OPTIONAL, -- Cond SLRBSetup + sl-PDCP-Config-r16 SL-PDCP-Config-r16 OPTIONAL, -- Cond SLRBSetup + sl-TransRange-r16 ENUMERATED {m20, m50, m80, m100, m120, m150, m180, m200, m220, m250, m270, m300, m350, m370, + m400, m420, m450, m480, m500, m550, m600, m700, m1000, spare9, spare8, spare7, spare6, + spare5, spare4, spare3, spare2, spare1} OPTIONAL, -- Need R + ... +} + +-- TAG-SL-RADIOBEARERCONFIG-STOP +-- TAG-SL-REPORTCONFIGLIST-START + +SL-ReportConfigList-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-ReportConfigId-r16)) OF SL-ReportConfigInfo-r16 + +SL-ReportConfigInfo-r16 ::= SEQUENCE { + sl-ReportConfigId-r16 SL-ReportConfigId-r16, + sl-ReportConfig-r16 SL-ReportConfig-r16, + ... +} + +SL-ReportConfigId-r16 ::= INTEGER (1..maxNrofSL-ReportConfigId-r16) + +SL-ReportConfig-r16 ::= SEQUENCE { + sl-ReportType-r16 CHOICE { + sl-Periodical-r16 SL-PeriodicalReportConfig-r16, + sl-EventTriggered-r16 SL-EventTriggerConfig-r16, + ... + }, + ... +} + +SL-PeriodicalReportConfig-r16 ::= SEQUENCE { + sl-ReportInterval-r16 ReportInterval, + sl-ReportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + sl-ReportQuantity-r16 SL-MeasReportQuantity-r16, + sl-RS-Type-r16 SL-RS-Type-r16, + ... +} + +SL-EventTriggerConfig-r16 ::= SEQUENCE { + sl-EventId-r16 CHOICE { + eventS1-r16 SEQUENCE { + s1-Threshold-r16 SL-MeasTriggerQuantity-r16, + sl-ReportOnLeave-r16 BOOLEAN, + sl-Hysteresis-r16 Hysteresis, + sl-TimeToTrigger-r16 TimeToTrigger, + ... + }, + eventS2-r16 SEQUENCE { + s2-Threshold-r16 SL-MeasTriggerQuantity-r16, + sl-ReportOnLeave-r16 BOOLEAN, + sl-Hysteresis-r16 Hysteresis, + sl-TimeToTrigger-r16 TimeToTrigger, + ... + }, + ... + }, + sl-ReportInterval-r16 ReportInterval, + sl-ReportAmount-r16 ENUMERATED {r1, r2, r4, r8, r16, r32, r64, infinity}, + sl-ReportQuantity-r16 SL-MeasReportQuantity-r16, + sl-RS-Type-r16 SL-RS-Type-r16, + ... +} + +SL-MeasReportQuantity-r16 ::= CHOICE { + sl-RSRP-r16 BOOLEAN, + ... +} + +SL-MeasTriggerQuantity-r16 ::= CHOICE { + sl-RSRP-r16 RSRP-Range, + ... +} + +SL-RS-Type-r16 ::= ENUMERATED {dmrs, spare3, spare2, spare1} + +-- TAG-SL-REPORTCONFIGLIST-STOP +-- TAG-SL-RESOURCEPOOL-START + +SL-ResourcePool-r16 ::= SEQUENCE { + sl-PSCCH-Config-r16 SetupRelease { SL-PSCCH-Config-r16 } OPTIONAL, -- Need M + sl-PSSCH-Config-r16 SetupRelease { SL-PSSCH-Config-r16 } OPTIONAL, -- Need M + sl-PSFCH-Config-r16 SetupRelease { SL-PSFCH-Config-r16 } OPTIONAL, -- Need M + sl-SyncAllowed-r16 SL-SyncAllowed-r16 OPTIONAL, -- Need M + sl-SubchannelSize-r16 ENUMERATED {n10, n12, n15, n20, n25, n50, n75, n100} OPTIONAL, -- Need M + dummy INTEGER (10..160) OPTIONAL, -- Need M + sl-StartRB-Subchannel-r16 INTEGER (0..265) OPTIONAL, -- Need M + sl-NumSubchannel-r16 INTEGER (1..27) OPTIONAL, -- Need M + sl-Additional-MCS-Table-r16 ENUMERATED {qam256, qam64LowSE, qam256-qam64LowSE } OPTIONAL, -- Need M + sl-ThreshS-RSSI-CBR-r16 INTEGER (0..45) OPTIONAL, -- Need M + sl-TimeWindowSizeCBR-r16 ENUMERATED {ms100, slot100} OPTIONAL, -- Need M + sl-TimeWindowSizeCR-r16 ENUMERATED {ms1000, slot1000} OPTIONAL, -- Need M + sl-PTRS-Config-r16 SL-PTRS-Config-r16 OPTIONAL, -- Need M + sl-UE-SelectedConfigRP-r16 SL-UE-SelectedConfigRP-r16 OPTIONAL, -- Need M + sl-RxParametersNcell-r16 SEQUENCE { + sl-TDD-Configuration-r16 TDD-UL-DL-ConfigCommon OPTIONAL, -- Need M + sl-SyncConfigIndex-r16 INTEGER (0..15) + } OPTIONAL, -- Need M + sl-ZoneConfigMCR-List-r16 SEQUENCE (SIZE (16)) OF SL-ZoneConfigMCR-r16 OPTIONAL, -- Need M + sl-FilterCoefficient-r16 FilterCoefficient OPTIONAL, -- Need M + sl-RB-Number-r16 INTEGER (10..275) OPTIONAL, -- Need M + sl-PreemptionEnable-r16 ENUMERATED {enabled, pl1, pl2, pl3, pl4, pl5, pl6, pl7, pl8} OPTIONAL, -- Need R + sl-PriorityThreshold-UL-URLLC-r16 INTEGER (1..9) OPTIONAL, -- Need M + sl-PriorityThreshold-r16 INTEGER (1..9) OPTIONAL, -- Need M + sl-X-Overhead-r16 ENUMERATED {n0,n3, n6, n9} OPTIONAL, -- Need S + sl-PowerControl-r16 SL-PowerControl-r16 OPTIONAL, -- Need M + sl-TxPercentageList-r16 SL-TxPercentageList-r16 OPTIONAL, -- Need M + sl-MinMaxMCS-List-r16 SL-MinMaxMCS-List-r16 OPTIONAL, -- Need M + ..., + [[ + sl-TimeResource-r16 BIT STRING (SIZE (10..160)) OPTIONAL -- Need M + ]] +} + +SL-ZoneConfigMCR-r16 ::= SEQUENCE { + sl-ZoneConfigMCR-Index-r16 INTEGER (0..15), + sl-TransRange-r16 ENUMERATED {m20, m50, m80, m100, m120, m150, m180, m200, m220, m250, m270, m300, m350, + m370, m400, m420, m450, m480, m500, m550, m600, m700, m1000, spare9, spare8, + spare7, spare6, spare5, spare4, spare3, spare2, spare1} + OPTIONAL, -- Need M + sl-ZoneConfig-r16 SL-ZoneConfig-r16 OPTIONAL, -- Need M + ... +} + +SL-SyncAllowed-r16 ::= SEQUENCE { + gnss-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R + gnbEnb-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R + ue-Sync-r16 ENUMERATED {true} OPTIONAL -- Need R +} + +SL-PSCCH-Config-r16 ::= SEQUENCE { + sl-TimeResourcePSCCH-r16 ENUMERATED {n2, n3} OPTIONAL, -- Need M + sl-FreqResourcePSCCH-r16 ENUMERATED {n10,n12, n15, n20, n25} OPTIONAL, -- Need M + sl-DMRS-ScrambleID-r16 INTEGER (0..65535) OPTIONAL, -- Need M + sl-NumReservedBits-r16 INTEGER (2..4) OPTIONAL, -- Need M + ... +} + +SL-PSSCH-Config-r16 ::= SEQUENCE { + sl-PSSCH-DMRS-TimePatternList-r16 SEQUENCE (SIZE (1..3)) OF INTEGER (2..4) OPTIONAL, -- Need M + sl-BetaOffsets2ndSCI-r16 SEQUENCE (SIZE (4)) OF SL-BetaOffsets-r16 OPTIONAL, -- Need M + sl-Scaling-r16 ENUMERATED {f0p5, f0p65, f0p8, f1} OPTIONAL, -- Need M + ... +} + +SL-PSFCH-Config-r16 ::= SEQUENCE { + sl-PSFCH-Period-r16 ENUMERATED {sl0, sl1, sl2, sl4} OPTIONAL, -- Need M + sl-PSFCH-RB-Set-r16 BIT STRING (SIZE (10..275)) OPTIONAL, -- Need M + sl-NumMuxCS-Pair-r16 ENUMERATED {n1, n2, n3, n6} OPTIONAL, -- Need M + sl-MinTimeGapPSFCH-r16 ENUMERATED {sl2, sl3} OPTIONAL, -- Need M + sl-PSFCH-HopID-r16 INTEGER (0..1023) OPTIONAL, -- Need M + sl-PSFCH-CandidateResourceType-r16 ENUMERATED {startSubCH, allocSubCH} OPTIONAL, -- Need M + ... +} +SL-PTRS-Config-r16 ::= SEQUENCE { + sl-PTRS-FreqDensity-r16 SEQUENCE (SIZE (2)) OF INTEGER (1..276) OPTIONAL, -- Need M + sl-PTRS-TimeDensity-r16 SEQUENCE (SIZE (3)) OF INTEGER (0..29) OPTIONAL, -- Need M + sl-PTRS-RE-Offset-r16 ENUMERATED {offset01, offset10, offset11} OPTIONAL, -- Need M + ... +} + +SL-UE-SelectedConfigRP-r16 ::= SEQUENCE { + sl-CBR-PriorityTxConfigList-r16 SL-CBR-PriorityTxConfigList-r16 OPTIONAL, -- Need M + sl-Thres-RSRP-List-r16 SL-Thres-RSRP-List-r16 OPTIONAL, -- Need M + sl-MultiReserveResource-r16 ENUMERATED {enabled} OPTIONAL, -- Need M + sl-MaxNumPerReserve-r16 ENUMERATED {n2, n3} OPTIONAL, -- Need M + sl-SensingWindow-r16 ENUMERATED {ms100, ms1100} OPTIONAL, -- Need M + sl-SelectionWindowList-r16 SL-SelectionWindowList-r16 OPTIONAL, -- Need M + sl-ResourceReservePeriodList-r16 SEQUENCE (SIZE (1..16)) OF SL-ResourceReservePeriod-r16 OPTIONAL, -- Need M + sl-RS-ForSensing-r16 ENUMERATED {pscch, pssch}, + ... +} + +SL-ResourceReservePeriod-r16 ::= CHOICE { + sl-ResourceReservePeriod1-r16 ENUMERATED {ms0, ms100, ms200, ms300, ms400, ms500, ms600, ms700, ms800, ms900, ms1000}, + sl-ResourceReservePeriod2-r16 INTEGER (1..99) +} + +SL-SelectionWindowList-r16 ::= SEQUENCE (SIZE (8)) OF SL-SelectionWindowConfig-r16 + +SL-SelectionWindowConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-SelectionWindow-r16 ENUMERATED {n1, n5, n10, n20} +} + +SL-TxPercentageList-r16 ::= SEQUENCE (SIZE (8)) OF SL-TxPercentageConfig-r16 + +SL-TxPercentageConfig-r16 ::= SEQUENCE { + sl-Priority-r16 INTEGER (1..8), + sl-TxPercentage-r16 ENUMERATED {p20, p35, p50} +} + +SL-MinMaxMCS-List-r16 ::= SEQUENCE (SIZE (1..3)) OF SL-MinMaxMCS-Config-r16 + +SL-MinMaxMCS-Config-r16 ::= SEQUENCE { + sl-MCS-Table-r16 ENUMERATED {qam64, qam256, qam64LowSE}, + sl-MinMCS-PSSCH-r16 INTEGER (0..27), + sl-MaxMCS-PSSCH-r16 INTEGER (0..31) +} + +SL-BetaOffsets-r16 ::= INTEGER (0..31) + +SL-PowerControl-r16 ::= SEQUENCE { + sl-MaxTransPower-r16 INTEGER (-30..33), + sl-Alpha-PSSCH-PSCCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need M + dl-Alpha-PSSCH-PSCCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need S + sl-P0-PSSCH-PSCCH-r16 INTEGER (-16..15) OPTIONAL, -- Need S + dl-P0-PSSCH-PSCCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + dl-Alpha-PSFCH-r16 ENUMERATED {alpha0, alpha04, alpha05, alpha06, alpha07, alpha08, alpha09, alpha1} OPTIONAL, -- Need S + dl-P0-PSFCH-r16 INTEGER (-16..15) OPTIONAL, -- Need M + ... +} + +-- TAG-SL-RESOURCEPOOL-STOP +-- TAG-SL-RLC-BEARERCONFIG-START + +SL-RLC-BearerConfig-r16 ::= SEQUENCE { + sl-RLC-BearerConfigIndex-r16 SL-RLC-BearerConfigIndex-r16, + sl-ServedRadioBearer-r16 SLRB-Uu-ConfigIndex-r16 OPTIONAL, -- Cond LCH-SetupOnly + sl-RLC-Config-r16 SL-RLC-Config-r16 OPTIONAL, -- Cond LCH-Setup + sl-MAC-LogicalChannelConfig-r16 SL-LogicalChannelConfig-r16 OPTIONAL, -- Cond LCH-Setup + ... +} + +-- TAG-SL-RLC-BEARERCONFIG-STOP +-- TAG-SL-RLC-BEARERCONFIGINDEX-START + +SL-RLC-BearerConfigIndex-r16 ::= INTEGER (1..maxSL-LCID-r16) + +-- TAG-RLC-BEARERCONFIGINDEX-STOP +-- TAG-SL-RLC-CONFIG-START + +SL-RLC-Config-r16 ::= CHOICE { + sl-AM-RLC-r16 SEQUENCE { + sl-SN-FieldLengthAM-r16 SN-FieldLengthAM OPTIONAL, -- Cond SLRBSetup + sl-T-PollRetransmit-r16 T-PollRetransmit, + sl-PollPDU-r16 PollPDU, + sl-PollByte-r16 PollByte, + sl-MaxRetxThreshold-r16 ENUMERATED { t1, t2, t3, t4, t6, t8, t16, t32 }, + ... + }, + sl-UM-RLC-r16 SEQUENCE { + sl-SN-FieldLengthUM-r16 SN-FieldLengthUM OPTIONAL, -- Cond SLRBSetup + ... + }, + ... +} + +-- TAG-SL-RLC-CONFIG-STOP +-- TAG-SL-SCHEDULEDCONFIG-START + +SL-ScheduledConfig-r16 ::= SEQUENCE { + sl-RNTI-r16 RNTI-Value, + mac-MainConfigSL-r16 MAC-MainConfigSL-r16 OPTIONAL, -- Need M + sl-CS-RNTI-r16 RNTI-Value OPTIONAL, -- Need M + sl-PSFCH-ToPUCCH-r16 SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) OPTIONAL, -- Need M + sl-ConfiguredGrantConfigList-r16 SL-ConfiguredGrantConfigList-r16 OPTIONAL, -- Need M + ..., + [[ + sl-DCI-ToSL-Trans-r16 SEQUENCE (SIZE (1..8)) OF INTEGER (1..32) OPTIONAL -- Need M + ]] +} + +MAC-MainConfigSL-r16 ::= SEQUENCE { + sl-BSR-Config-r16 BSR-Config OPTIONAL, -- Need M + ul-PrioritizationThres-r16 INTEGER (1..16) OPTIONAL, -- Need M + sl-PrioritizationThres-r16 INTEGER (1..8) OPTIONAL, -- Need M + ... +} + +SL-ConfiguredGrantConfigList-r16 ::= SEQUENCE { + sl-ConfiguredGrantConfigToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofCG-SL-r16)) OF SL-ConfigIndexCG-r16 OPTIONAL, -- Need N + sl-ConfiguredGrantConfigToAddModList-r16 SEQUENCE (SIZE (1..maxNrofCG-SL-r16)) OF SL-ConfiguredGrantConfig-r16 OPTIONAL -- Need N +} + +-- TAG-SL-SCHEDULEDCONFIG-STOP +-- TAG-SL-SDAP-CONFIG-START + +SL-SDAP-Config-r16 ::= SEQUENCE { + sl-SDAP-Header-r16 ENUMERATED {present, absent}, + sl-DefaultRB-r16 BOOLEAN, + sl-MappedQoS-Flows-r16 CHOICE { + sl-MappedQoS-FlowsList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-Profile-r16, + sl-MappedQoS-FlowsListDedicated-r16 SL-MappedQoS-FlowsListDedicated-r16 + } OPTIONAL, -- Need M + sl-CastType-r16 ENUMERATED {broadcast, groupcast, unicast, spare1} OPTIONAL, -- Need M + ... +} + +SL-MappedQoS-FlowsListDedicated-r16 ::= SEQUENCE { + sl-MappedQoS-FlowsToAddList-r16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-FlowIdentity-r16 OPTIONAL, -- Need N + sl-MappedQoS-FlowsToReleaseList-16 SEQUENCE (SIZE (1..maxNrofSL-QFIs-r16)) OF SL-QoS-FlowIdentity-r16 OPTIONAL -- Need N +} + +-- TAG-SL-SDAP-CONFIG-STOP +-- TAG-SL-SYNCCONFIG-START + +SL-SyncConfigList-r16 ::= SEQUENCE (SIZE (1..maxSL-SyncConfig-r16)) OF SL-SyncConfig-r16 + +SL-SyncConfig-r16 ::= SEQUENCE { + sl-SyncRefMinHyst-r16 ENUMERATED {dB0, dB3, dB6, dB9, dB12} OPTIONAL, -- Need R + sl-SyncRefDiffHyst-r16 ENUMERATED {dB0, dB3, dB6, dB9, dB12, dBinf} OPTIONAL, -- Need R + sl-filterCoefficient-r16 FilterCoefficient OPTIONAL, -- Need R + sl-SSB-TimeAllocation1-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSB-TimeAllocation2-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSB-TimeAllocation3-r16 SL-SSB-TimeAllocation-r16 OPTIONAL, -- Need R + sl-SSID-r16 INTEGER (0..671) OPTIONAL, -- Need R + txParameters-r16 SEQUENCE { + syncTxThreshIC-r16 SL-RSRP-Range-r16 OPTIONAL, -- Need R + syncTxThreshOoC-r16 SL-RSRP-Range-r16 OPTIONAL, -- Need R + syncInfoReserved-r16 BIT STRING (SIZE (2)) OPTIONAL -- Need R + }, + gnss-Sync-r16 ENUMERATED {true} OPTIONAL, -- Need R + ... +} + +SL-RSRP-Range-r16 ::= INTEGER (0..13) + +SL-SSB-TimeAllocation-r16 ::= SEQUENCE { + sl-NumSSB-WithinPeriod-r16 ENUMERATED {n1, n2, n4, n8, n16, n32, n64} OPTIONAL, -- Need R + sl-TimeOffsetSSB-r16 INTEGER (0..1279) OPTIONAL, -- Need R + sl-TimeInterval-r16 INTEGER (0..639) OPTIONAL -- Need R +} + +-- TAG-SL-SYNCCONFIG-STOP +-- TAG-SL-THRES-RSRP-LIST-START + +SL-Thres-RSRP-List-r16 ::= SEQUENCE (SIZE (64)) OF SL-Thres-RSRP-r16 + +SL-Thres-RSRP-r16 ::= INTEGER (0..66) + +-- TAG-SL-THRES-RSRP-LIST-STOP +-- TAG-SL-TXPOWER-START + +SL-TxPower-r16 ::= CHOICE{ + minusinfinity-r16 NULL, + txPower-r16 INTEGER (-30..33) +} + +-- TAG-SL-TXPOWER-STOP +-- TAG-SL-TYPETXSYNC-START + +SL-TypeTxSync-r16 ::= ENUMERATED {gnss, gnbEnb, ue} + +-- TAG-SL-TYPETXSYNC-STOP +-- TAG-SL-UE-SELECTEDCONFIG-START + +SL-UE-SelectedConfig-r16 ::= SEQUENCE { + sl-PSSCH-TxConfigList-r16 SL-PSSCH-TxConfigList-r16 OPTIONAL, -- Need R + sl-ProbResourceKeep-r16 ENUMERATED {v0, v0dot2, v0dot4, v0dot6, v0dot8} OPTIONAL, -- Need R + sl-ReselectAfter-r16 ENUMERATED {n1, n2, n3, n4, n5, n6, n7, n8, n9} OPTIONAL, -- Need R + sl-CBR-CommonTxConfigList-r16 SL-CBR-CommonTxConfigList-r16 OPTIONAL, -- Need R + ul-PrioritizationThres-r16 INTEGER (1..16) OPTIONAL, -- Need R + sl-PrioritizationThres-r16 INTEGER (1..8) OPTIONAL, -- Need R + ... +} + +-- TAG-SL-UE-SELECTEDCONFIG-STOP +-- TAG-SL-ZONECONFIG-START + +SL-ZoneConfig-r16 ::= SEQUENCE { + sl-ZoneLength-r16 ENUMERATED { m5, m10, m20, m30, m40, m50, spare2, spare1}, + ... +} + +-- TAG-SL-ZONECONFIG-STOP +-- TAG-SLRB-UU-CONFIGINDEX-START + +SLRB-Uu-ConfigIndex-r16 ::= INTEGER (1..maxNrofSLRB-r16) + +-- TAG-SLRB-UU-CONFIGINDEX-STOP +-- TAG-MULTIPLICITY-AND-TYPE-CONSTRAINT-DEFINITIONS-START + +maxAI-DCI-PayloadSize-r16 INTEGER ::= 128 --Maximum size of the DCI payload scrambled with ai-RNTI +maxAI-DCI-PayloadSize-r16-1 INTEGER ::= 127 --Maximum size of the DCI payload scrambled with ai-RNTI minus 1 +maxBandComb INTEGER ::= 65536 -- Maximum number of DL band combinations +maxBandsUTRA-FDD-r16 INTEGER ::= 64 -- Maximum number of bands listed in UTRA-FDD UE caps +maxBH-RLC-ChannelID-r16 INTEGER ::= 65536 -- Maximum value of BH RLC Channel ID +maxBT-IdReport-r16 INTEGER ::= 32 -- Maximum number of Bluetooth IDs to report +maxBT-Name-r16 INTEGER ::= 4 -- Maximum number of Bluetooth name +maxCAG-Cell-r16 INTEGER ::= 16 -- Maximum number of NR CAG cell ranges in SIB3, SIB4 +maxTwoPUCCH-Grp-ConfigList-r16 INTEGER ::= 32 -- Maximum number of supported configuration(s) of {primary PUCCH group + -- config, secondary PUCCH group config} +maxCBR-Config-r16 INTEGER ::= 8 -- Maximum number of CBR range configurations for sidelink communication + -- congestion control +maxCBR-Config-1-r16 INTEGER ::= 7 -- Maximum number of CBR range configurations for sidelink communication + -- congestion control minus 1 +maxCBR-Level-r16 INTEGER ::= 16 -- Maximum nuber of CBR levels +maxCBR-Level-1-r16 INTEGER ::= 15 -- Maximum number of CBR levels minus 1 +maxCellBlack INTEGER ::= 16 -- Maximum number of NR blacklisted cell ranges in SIB3, SIB4 +maxCellHistory-r16 INTEGER ::= 16 -- Maximum number of visited cells reported +maxCellInter INTEGER ::= 16 -- Maximum number of inter-Freq cells listed in SIB4 +maxCellIntra INTEGER ::= 16 -- Maximum number of intra-Freq cells listed in SIB3 +maxCellMeasEUTRA INTEGER ::= 32 -- Maximum number of cells in E-UTRAN +maxCellMeasIdle-r16 INTEGER ::= 8 -- Maximum number of cells per carrier for idle/inactive measurements +maxCellMeasUTRA-FDD-r16 INTEGER ::= 32 -- Maximum number of cells in FDD UTRAN +maxCellWhite INTEGER ::= 16 -- Maximum number of NR whitelisted cell ranges in SIB3, SIB4 +maxEARFCN INTEGER ::= 262143 -- Maximum value of E-UTRA carrier frequency +maxEUTRA-CellBlack INTEGER ::= 16 -- Maximum number of E-UTRA blacklisted physical cell identity ranges + -- in SIB5 +maxEUTRA-NS-Pmax INTEGER ::= 8 -- Maximum number of NS and P-Max values per band +maxLogMeasReport-r16 INTEGER ::= 520 -- Maximum number of entries for logged measurements +maxMultiBands INTEGER ::= 8 -- Maximum number of additional frequency bands that a cell belongs to +maxNARFCN INTEGER ::= 3279165 -- Maximum value of NR carrier frequency +maxNR-NS-Pmax INTEGER ::= 8 -- Maximum number of NS and P-Max values per band +maxFreqIdle-r16 INTEGER ::= 8 -- Maximum number of carrier frequencies for idle/inactive measurements +maxNrofServingCells INTEGER ::= 32 -- Max number of serving cells (SpCells + SCells) +maxNrofServingCells-1 INTEGER ::= 31 -- Max number of serving cells (SpCell + SCells) per cell group +maxNrofAggregatedCellsPerCellGroup INTEGER ::= 16 +maxNrofDUCells-r16 INTEGER ::= 512 -- Max number of cells configured on the collocated IAB-DU +maxNrofAssociatedDUCellsPerMT-r16 INTEGER ::= 65535 +maxNrofAvailabilityCombinationsPerSet-r16 INTEGER ::= 512 -- Max number of AvailabilityCombinationId used in the DCI format 2_5 +maxNrofAvailabilityCombinationsPerSet-r16-1 INTEGER ::= 511 -- Max number of AvailabilityCombinationId used in the DCI format 2_5 minus 1 +maxNrofSCells INTEGER ::= 31 -- Max number of secondary serving cells per cell group +maxNrofCellMeas INTEGER ::= 32 -- Maximum number of entries in each of the cell lists in a measurement object +maxNrofCG-SL-r16 INTEGER ::= 8 -- Max number of sidelink configured grant +maxNrofCG-SL-r16-1 INTEGER ::= 7 -- Max number of sidelink configured grant minus 1 +maxNrofSS-BlocksToAverage INTEGER ::= 16 -- Max number for the (max) number of SS blocks to average to determine cell measurement +maxNrofCondCells-r16 INTEGER ::= 8 -- Max number of conditional candidate SpCells +maxNrofCSI-RS-ResourcesToAverage INTEGER ::= 16 -- Max number for the (max) number of CSI-RS to average to determine cell measurement +maxNrofDL-Allocations INTEGER ::= 16 -- Maximum number of PDSCH time domain resource allocations +maxNrofSR-ConfigPerCellGroup INTEGER ::= 8 -- Maximum number of SR configurations per cell group +maxLCG-ID INTEGER ::= 7 -- Maximum value of LCG ID +maxLC-ID INTEGER ::= 32 -- Maximum value of Logical Channel ID +maxLC-ID-Iab-r16 INTEGER ::= 65855 -- Maximum value of BH Logical Channel ID extension +maxLTE-CRS-Patterns-r16 INTEGER ::= 3 -- Maximum number of additional LTE CRS rate matching patterns +maxNrofTAGs INTEGER ::= 4 -- Maximum number of Timing Advance Groups +maxNrofTAGs-1 INTEGER ::= 3 -- Maximum number of Timing Advance Groups minus 1 +maxNrofBWPs INTEGER ::= 4 -- Maximum number of BWPs per serving cell +maxNrofCombIDC INTEGER ::= 128 -- Maximum number of reported MR-DC combinations for IDC +maxNrofSymbols-1 INTEGER ::= 13 -- Maximum index identifying a symbol within a slot (14 symbols, indexed from 0..13) +maxNrofSlots INTEGER ::= 320 -- Maximum number of slots in a 10 ms period +maxNrofSlots-1 INTEGER ::= 319 -- Maximum number of slots in a 10 ms period minus 1 +maxNrofPhysicalResourceBlocks INTEGER ::= 275 -- Maximum number of PRBs +maxNrofPhysicalResourceBlocks-1 INTEGER ::= 274 -- Maximum number of PRBs minus 1 +maxNrofPhysicalResourceBlocksPlus1 INTEGER ::= 276 -- Maximum number of PRBs plus 1 +maxNrofControlResourceSets INTEGER ::= 12 -- Max number of CoReSets configurable on a serving cell +maxNrofControlResourceSets-1 INTEGER ::= 11 -- Max number of CoReSets configurable on a serving cell minus 1 +maxNrofControlResourceSets-1-r16 INTEGER ::= 15 -- Max number of CoReSets configurable on a serving cell extended in minus 1 +maxNrofCoresetPools-r16 INTEGER ::= 2 -- Maximum number of CORESET pools +maxCoReSetDuration INTEGER ::= 3 -- Max number of OFDM symbols in a control resource set +maxNrofSearchSpaces-1 INTEGER ::= 39 -- Max number of Search Spaces minus 1 +maxSFI-DCI-PayloadSize INTEGER ::= 128 -- Max number payload of a DCI scrambled with SFI-RNTI +maxSFI-DCI-PayloadSize-1 INTEGER ::= 127 -- Max number payload of a DCI scrambled with SFI-RNTI minus 1 +maxIAB-IP-Address-r16 INTEGER ::= 32 -- Max number of assigned IP addresses +maxINT-DCI-PayloadSize INTEGER ::= 126 -- Max number payload of a DCI scrambled with INT-RNTI +maxINT-DCI-PayloadSize-1 INTEGER ::= 125 -- Max number payload of a DCI scrambled with INT-RNTI minus 1 +maxNrofRateMatchPatterns INTEGER ::= 4 -- Max number of rate matching patterns that may be configured +maxNrofRateMatchPatterns-1 INTEGER ::= 3 -- Max number of rate matching patterns that may be configured minus 1 +maxNrofRateMatchPatternsPerGroup INTEGER ::= 8 -- Max number of rate matching patterns that may be configured in one group +maxNrofCSI-ReportConfigurations INTEGER ::= 48 -- Maximum number of report configurations +maxNrofCSI-ReportConfigurations-1 INTEGER ::= 47 -- Maximum number of report configurations minus 1 +maxNrofCSI-ResourceConfigurations INTEGER ::= 112 -- Maximum number of resource configurations +maxNrofCSI-ResourceConfigurations-1 INTEGER ::= 111 -- Maximum number of resource configurations minus 1 +maxNrofAP-CSI-RS-ResourcesPerSet INTEGER ::= 16 +maxNrOfCSI-AperiodicTriggers INTEGER ::= 128 -- Maximum number of triggers for aperiodic CSI reporting +maxNrofReportConfigPerAperiodicTrigger INTEGER ::= 16 -- Maximum number of report configurations per trigger state for aperiodic reporting +maxNrofNZP-CSI-RS-Resources INTEGER ::= 192 -- Maximum number of Non-Zero-Power (NZP) CSI-RS resources +maxNrofNZP-CSI-RS-Resources-1 INTEGER ::= 191 -- Maximum number of Non-Zero-Power (NZP) CSI-RS resources minus 1 +maxNrofNZP-CSI-RS-ResourcesPerSet INTEGER ::= 64 -- Maximum number of NZP CSI-RS resources per resource set +maxNrofNZP-CSI-RS-ResourceSets INTEGER ::= 64 -- Maximum number of NZP CSI-RS resources per cell +maxNrofNZP-CSI-RS-ResourceSets-1 INTEGER ::= 63 -- Maximum number of NZP CSI-RS resources per cell minus 1 +maxNrofNZP-CSI-RS-ResourceSetsPerConfig INTEGER ::= 16 -- Maximum number of resource sets per resource configuration +maxNrofNZP-CSI-RS-ResourcesPerConfig INTEGER ::= 128 -- Maximum number of resources per resource configuration +maxNrofZP-CSI-RS-Resources INTEGER ::= 32 -- Maximum number of Zero-Power (ZP) CSI-RS resources +maxNrofZP-CSI-RS-Resources-1 INTEGER ::= 31 -- Maximum number of Zero-Power (ZP) CSI-RS resources minus 1 +maxNrofZP-CSI-RS-ResourceSets-1 INTEGER ::= 15 +maxNrofZP-CSI-RS-ResourcesPerSet INTEGER ::= 16 +maxNrofZP-CSI-RS-ResourceSets INTEGER ::= 16 +maxNrofCSI-IM-Resources INTEGER ::= 32 -- Maximum number of CSI-IM resources. See CSI-IM-ResourceMax in 38.214. +maxNrofCSI-IM-Resources-1 INTEGER ::= 31 -- Maximum number of CSI-IM resources minus 1. See CSI-IM-ResourceMax in 38.214. +maxNrofCSI-IM-ResourcesPerSet INTEGER ::= 8 -- Maximum number of CSI-IM resources per set. See CSI-IM-ResourcePerSetMax in 38.214 +maxNrofCSI-IM-ResourceSets INTEGER ::= 64 -- Maximum number of NZP CSI-IM resources per cell +maxNrofCSI-IM-ResourceSets-1 INTEGER ::= 63 -- Maximum number of NZP CSI-IM resources per cell minus 1 +maxNrofCSI-IM-ResourceSetsPerConfig INTEGER ::= 16 -- Maximum number of CSI IM resource sets per resource configuration +maxNrofCSI-SSB-ResourcePerSet INTEGER ::= 64 -- Maximum number of SSB resources in a resource set +maxNrofCSI-SSB-ResourceSets INTEGER ::= 64 -- Maximum number of CSI SSB resource sets per cell +maxNrofCSI-SSB-ResourceSets-1 INTEGER ::= 63 -- Maximum number of CSI SSB resource sets per cell minus 1 +maxNrofCSI-SSB-ResourceSetsPerConfig INTEGER ::= 1 -- Maximum number of CSI SSB resource sets per resource configuration +maxNrofFailureDetectionResources INTEGER ::= 10 -- Maximum number of failure detection resources +maxNrofFailureDetectionResources-1 INTEGER ::= 9 -- Maximum number of failure detection resources minus 1 +maxNrofFreqSL-r16 INTEGER ::= 8 -- Maximum number of carrier frequncy for for NR sidelink communication +maxNrofSL-BWPs-r16 INTEGER ::= 4 -- Maximum number of BWP for for NR sidelink communication +maxFreqSL-EUTRA-r16 INTEGER ::= 8 -- Maximum number of EUTRA anchor carrier frequncy for NR sidelink communication +maxNrofSL-MeasId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement identity (RSRP) per destination +maxNrofSL-ObjectId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement objects (RSRP) per destination +maxNrofSL-ReportConfigId-r16 INTEGER ::= 64 -- Maximum number of sidelink measurement reporting configuration(RSRP) per destination +maxNrofSL-PoolToMeasureNR-r16 INTEGER ::= 8 -- Maximum number of resoure pool for NR sidelink measurement to measure for + -- each measurement object (for CBR) +maxFreqSL-NR-r16 INTEGER ::= 8 -- Maximum number of NR anchor carrier frequncy for NR sidelink communication +maxNrofSL-QFIs-r16 INTEGER ::= 2048 -- Maximum number of QoS flow for NR sidelink communication per UE +maxNrofSL-QFIsPerDest-r16 INTEGER ::= 64 -- Maximum number of QoS flow per destination for NR sidelink communication +maxNrofObjectId INTEGER ::= 64 -- Maximum number of measurement objects +maxNrofPageRec INTEGER ::= 32 -- Maximum number of page records +maxNrofPCI-Ranges INTEGER ::= 8 -- Maximum number of PCI ranges +maxPLMN INTEGER ::= 12 -- Maximum number of PLMNs broadcast and reported by UE at establisghment +maxNrofCSI-RS-ResourcesRRM INTEGER ::= 96 -- Maximum number of CSI-RS resources per cell for an RRM measurement object +maxNrofCSI-RS-ResourcesRRM-1 INTEGER ::= 95 -- Maximum number of CSI-RS resources per cell for an RRM measurement object minus 1 +maxNrofMeasId INTEGER ::= 64 -- Maximum number of configured measurements +maxNrofQuantityConfig INTEGER ::= 2 -- Maximum number of quantity configurations +maxNrofCSI-RS-CellsRRM INTEGER ::= 96 -- Maximum number of cells with CSI-RS resources for an RRM measurement object +maxNrofSL-Dest-r16 INTEGER ::= 32 -- Maximum number of destination for NR sidelink communication +maxNrofSL-Dest-1-r16 INTEGER ::= 31 -- Highest index of destination for NR sidelink communication +maxNrofSLRB-r16 INTEGER ::= 512 -- Maximum number of radio bearer for NR sidelink communication per UE +maxSL-LCID-r16 INTEGER ::= 512 -- Maximum number of RLC bearer for NR sidelink communication per UE +maxSL-SyncConfig-r16 INTEGER ::= 16 -- Maximum number of sidelink Sync configurations +maxNrofRXPool-r16 INTEGER ::= 16 -- Maximum number of Rx resource poolfor NR sidelink communication +maxNrofTXPool-r16 INTEGER ::= 8 -- Maximum number of Tx resourcepoolfor NR sidelink communication +maxNrofPoolID-r16 INTEGER ::= 16 -- Maximum index of resource pool for NR sidelink communication +maxNrofSRS-PathlossReferenceRS-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for SRS power control. +maxNrofSRS-PathlossReferenceRS-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for SRS power control-1. +maxNrofSRS-ResourceSets INTEGER ::= 16 -- Maximum number of SRS resource sets in a BWP. +maxNrofSRS-ResourceSets-1 INTEGER ::= 15 -- Maximum number of SRS resource sets in a BWP minus 1. +maxNrofSRS-PosResourceSets-r16 INTEGER ::= 16 -- Maximum number of SRS Positioning resource sets in a BWP. +maxNrofSRS-PosResourceSets-1-r16 INTEGER ::= 15 -- Maximum number of SRS Positioning resource sets in a BWP minus 1. +maxNrofSRS-Resources INTEGER ::= 64 -- Maximum number of SRS resources. +maxNrofSRS-Resources-1 INTEGER ::= 63 -- Maximum number of SRS resources minus 1. +maxNrofSRS-PosResources-r16 INTEGER ::= 64 -- Maximum number of SRS Positioning resources. +maxNrofSRS-PosResources-1-r16 INTEGER ::= 63 -- Maximum number of SRS Positioning resources in an SRS Positioning + -- resource set minus 1. +maxNrofSRS-ResourcesPerSet INTEGER ::= 16 -- Maximum number of SRS resources in an SRS resource set +maxNrofSRS-TriggerStates-1 INTEGER ::= 3 -- Maximum number of SRS trigger states minus 1, i.e., the largest code point. +maxNrofSRS-TriggerStates-2 INTEGER ::= 2 -- Maximum number of SRS trigger states minus 2. +maxRAT-CapabilityContainers INTEGER ::= 8 -- Maximum number of interworking RAT containers (incl NR and MRDC) +maxSimultaneousBands INTEGER ::= 32 -- Maximum number of simultaneously aggregated bands +maxULTxSwitchingBandPairs INTEGER ::= 32 -- Maximum number of band pairs supporting dynamic UL Tx switching in a band combination +maxNrofSlotFormatCombinationsPerSet INTEGER ::= 512 -- Maximum number of Slot Format Combinations in a SF-Set. +maxNrofSlotFormatCombinationsPerSet-1 INTEGER ::= 511 -- Maximum number of Slot Format Combinations in a SF-Set minus 1. +maxNrofTrafficPattern-r16 INTEGER ::= 8 -- Maximum number of Traffic Pattern for NR sidelink communication. +maxNrofPUCCH-Resources INTEGER ::= 128 +maxNrofPUCCH-Resources-1 INTEGER ::= 127 +maxNrofPUCCH-ResourceSets INTEGER ::= 4 -- Maximum number of PUCCH Resource Sets +maxNrofPUCCH-ResourceSets-1 INTEGER ::= 3 -- Maximum number of PUCCH Resource Sets minus 1. +maxNrofPUCCH-ResourcesPerSet INTEGER ::= 32 -- Maximum number of PUCCH Resources per PUCCH-ResourceSet +maxNrofPUCCH-P0-PerSet INTEGER ::= 8 -- Maximum number of P0-pucch present in a p0-pucch set +maxNrofPUCCH-PathlossReferenceRSs INTEGER ::= 4 -- Maximum number of RSs used as pathloss reference for PUCCH power control. +maxNrofPUCCH-PathlossReferenceRSs-1 INTEGER ::= 3 -- Maximum number of RSs used as pathloss reference for PUCCH power control minus 1. +maxNrofPUCCH-PathlossReferenceRSs-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for PUCCH power control extended. +maxNrofPUCCH-PathlossReferenceRSs-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for PUCCH power control + -- minus 1 extended. +maxNrofPUCCH-PathlossReferenceRSsDiff-r16 INTEGER ::= 60 -- Difference between the extended maximum and the non-extended maximum +maxNrofPUCCH-ResourceGroups-r16 INTEGER ::= 4 -- Maximum number of PUCCH resources groups. +maxNrofPUCCH-ResourcesPerGroup-r16 INTEGER ::= 128 -- Maximum number of PUCCH resources in a PUCCH group. +maxNrofMultiplePUSCHs-r16 INTEGER ::= 8 -- Maximum number of multiple PUSCHs in PUSCH TDRA list +maxNrofP0-PUSCH-AlphaSets INTEGER ::= 30 -- Maximum number of P0-pusch-alpha-sets (see 38,213, clause 7.1) +maxNrofP0-PUSCH-AlphaSets-1 INTEGER ::= 29 -- Maximum number of P0-pusch-alpha-sets minus 1 (see 38,213, clause 7.1) +maxNrofPUSCH-PathlossReferenceRSs INTEGER ::= 4 -- Maximum number of RSs used as pathloss reference for PUSCH power control. +maxNrofPUSCH-PathlossReferenceRSs-1 INTEGER ::= 3 -- Maximum number of RSs used as pathloss reference for PUSCH power control minus 1. +maxNrofPUSCH-PathlossReferenceRSs-r16 INTEGER ::= 64 -- Maximum number of RSs used as pathloss reference for PUSCH power control extended +maxNrofPUSCH-PathlossReferenceRSs-1-r16 INTEGER ::= 63 -- Maximum number of RSs used as pathloss reference for PUSCH power control minus 1 +maxNrofPUSCH-PathlossReferenceRSsDiff-r16 INTEGER ::= 60 -- Difference between maxNrofPUSCH-PathlossReferenceRSs-r16 and + -- maxNrofPUSCH-PathlossReferenceRSs +maxNrofNAICS-Entries INTEGER ::= 8 -- Maximum number of supported NAICS capability set +maxBands INTEGER ::= 1024 -- Maximum number of supported bands in UE capability. +maxBandsMRDC INTEGER ::= 1280 +maxBandsEUTRA INTEGER ::= 256 +maxCellReport INTEGER ::= 8 +maxDRB INTEGER ::= 29 -- Maximum number of DRBs (that can be added in DRB-ToAddModLIst). +maxFreq INTEGER ::= 8 -- Max number of frequencies. +maxFreqLayers INTEGER ::= 4 -- Max number of frequency layers. +maxFreqIDC-r16 INTEGER ::= 128 -- Max number of frequencies for IDC indication. +maxCombIDC-r16 INTEGER ::= 128 -- Max number of reported UL CA for IDC indication. +maxFreqIDC-MRDC INTEGER ::= 32 -- Maximum number of candidate NR frequencies for MR-DC IDC indication +maxNrofCandidateBeams INTEGER ::= 16 -- Max number of PRACH-ResourceDedicatedBFR that in BFR config. +maxNrofCandidateBeams-r16 INTEGER ::= 64 -- Max number of candidate beam resources in BFR config. +maxNrofCandidateBeamsExt-r16 INTEGER ::= 48 -- Max number of PRACH-ResourceDedicatedBFR in the CandidateBeamRSListExt +maxNrofPCIsPerSMTC INTEGER ::= 64 -- Maximun number of PCIs per SMTC. +maxNrofQFIs INTEGER ::= 64 +maxNrofResourceAvailabilityPerCombination-r16 INTEGER ::= 256 +maxNrOfSemiPersistentPUSCH-Triggers INTEGER ::= 64 -- Maximum number of triggers for semi persistent reporting on PUSCH +maxNrofSR-Resources INTEGER ::= 8 -- Maximum number of SR resources per BWP in a cell. +maxNrofSlotFormatsPerCombination INTEGER ::= 256 +maxNrofSpatialRelationInfos INTEGER ::= 8 +maxNrofSpatialRelationInfos-plus-1 INTEGER ::= 9 +maxNrofSpatialRelationInfos-r16 INTEGER ::= 64 +maxNrofSpatialRelationInfosDiff-r16 INTEGER ::= 56 -- Difference between maxNrofSpatialRelationInfos-r16 and maxNrofSpatialRelationInfos +maxNrofIndexesToReport INTEGER ::= 32 +maxNrofIndexesToReport2 INTEGER ::= 64 +maxNrofSSBs-r16 INTEGER ::= 64 -- Maximum number of SSB resources in a resource set. +maxNrofSSBs-1 INTEGER ::= 63 -- Maximum number of SSB resources in a resource set minus 1. +maxNrofS-NSSAI INTEGER ::= 8 -- Maximum number of S-NSSAI. +maxNrofTCI-StatesPDCCH INTEGER ::= 64 +maxNrofTCI-States INTEGER ::= 128 -- Maximum number of TCI states. +maxNrofTCI-States-1 INTEGER ::= 127 -- Maximum number of TCI states minus 1. +maxNrofUL-Allocations INTEGER ::= 16 -- Maximum number of PUSCH time domain resource allocations. +maxQFI INTEGER ::= 63 +maxRA-CSIRS-Resources INTEGER ::= 96 +maxRA-OccasionsPerCSIRS INTEGER ::= 64 -- Maximum number of RA occasions for one CSI-RS +maxRA-Occasions-1 INTEGER ::= 511 -- Maximum number of RA occasions in the system +maxRA-SSB-Resources INTEGER ::= 64 +maxSCSs INTEGER ::= 5 +maxSecondaryCellGroups INTEGER ::= 3 +maxNrofServingCellsEUTRA INTEGER ::= 32 +maxMBSFN-Allocations INTEGER ::= 8 +maxNrofMultiBands INTEGER ::= 8 +maxCellSFTD INTEGER ::= 3 -- Maximum number of cells for SFTD reporting +maxReportConfigId INTEGER ::= 64 +maxNrofCodebooks INTEGER ::= 16 -- Maximum number of codebooks suppoted by the UE +maxNrofCSI-RS-ResourcesExt-r16 INTEGER ::= 16 -- Maximum number of codebook resources supported by the UE for eType2/Codebook combo +maxNrofCSI-RS-Resources INTEGER ::= 7 -- Maximum number of codebook resources supported by the UE +maxNrofCSI-RS-ResourcesAlt-r16 INTEGER ::= 512 -- Maximum number of alternative codebook resources supported by the UE +maxNrofCSI-RS-ResourcesAlt-1-r16 INTEGER ::= 511 -- Maximum number of alternative codebook resources supported by the UE minus 1 +maxNrofSRI-PUSCH-Mappings INTEGER ::= 16 +maxNrofSRI-PUSCH-Mappings-1 INTEGER ::= 15 +maxSIB INTEGER::= 32 -- Maximum number of SIBs +maxSI-Message INTEGER::= 32 -- Maximum number of SI messages +maxPO-perPF INTEGER ::= 4 -- Maximum number of paging occasion per paging frame +maxAccessCat-1 INTEGER ::= 63 -- Maximum number of Access Categories minus 1 +maxBarringInfoSet INTEGER ::= 8 -- Maximum number of Access Categories +maxCellEUTRA INTEGER ::= 8 -- Maximum number of E-UTRA cells in SIB list +maxEUTRA-Carrier INTEGER ::= 8 -- Maximum number of E-UTRA carriers in SIB list +maxPLMNIdentities INTEGER ::= 8 -- Maximum number of PLMN identites in RAN area configurations +maxDownlinkFeatureSets INTEGER ::= 1024 -- (for NR DL) Total number of FeatureSets (size of the pool) +maxUplinkFeatureSets INTEGER ::= 1024 -- (for NR UL) Total number of FeatureSets (size of the pool) +maxEUTRA-DL-FeatureSets INTEGER ::= 256 -- (for E-UTRA) Total number of FeatureSets (size of the pool) +maxEUTRA-UL-FeatureSets INTEGER ::= 256 -- (for E-UTRA) Total number of FeatureSets (size of the pool) +maxFeatureSetsPerBand INTEGER ::= 128 -- (for NR) The number of feature sets associated with one band. +maxPerCC-FeatureSets INTEGER ::= 1024 -- (for NR) Total number of CC-specific FeatureSets (size of the pool) +maxFeatureSetCombinations INTEGER ::= 1024 -- (for MR-DC/NR)Total number of Feature set combinations (size of the pool) +maxInterRAT-RSTD-Freq INTEGER ::= 3 +maxHRNN-Len-r16 INTEGER ::= 48 -- Maximum length of HRNNs +maxNPN-r16 INTEGER ::= 12 -- Maximum number of NPNs broadcast and reported by UE at establishment +maxNrOfMinSchedulingOffsetValues-r16 INTEGER ::= 2 -- Maximum number of min. scheduling offset (K0/K2) configurations +maxK0-SchedulingOffset-r16 INTEGER ::= 16 -- Maximum number of slots configured as min. scheduling offset (K0) +maxK2-SchedulingOffset-r16 INTEGER ::= 16 -- Maximum number of slots configured as min. scheduling offset (K2) +maxDCI-2-6-Size-r16 INTEGER ::= 140 -- Maximum size of DCI format 2-6 +maxDCI-2-6-Size-1-r16 INTEGER ::= 139 -- Maximum DCI format 2-6 size minus 1 +maxNrofUL-Allocations-r16 INTEGER ::= 64 -- Maximum number of PUSCH time domain resource allocations +maxNrofP0-PUSCH-Set-r16 INTEGER ::= 2 -- Maximum number of P0 PUSCH set(s) +maxOnDemandSIB-r16 INTEGER ::= 8 -- Maximum number of SIB(s) that can be requested on-demand +maxOnDemandPosSIB-r16 INTEGER ::= 32 -- Maximum number of posSIB(s) that can be requested on-demand +maxCI-DCI-PayloadSize-r16 INTEGER ::= 126 -- Maximum number of the DCI size for CI +maxCI-DCI-PayloadSize-r16-1 INTEGER ::= 125 -- Maximum number of the DCI size for CI minus 1 +maxWLAN-Id-Report-r16 INTEGER ::= 32 -- Maximum number of WLAN IDs to report +maxWLAN-Name-r16 INTEGER ::= 4 -- Maximum number of WLAN name +maxRAReport-r16 INTEGER ::= 8 -- Maximum number of RA procedures information to be included in the RA report +maxTxConfig-r16 INTEGER ::= 64 -- Maximum number of sidelink transmission parameters configurations +maxTxConfig-1-r16 INTEGER ::= 63 -- Maximum number of sidelink transmission parameters configurations minus 1 +maxPSSCH-TxConfig-r16 INTEGER ::= 16 -- Maximum number of PSSCH TX configurations +maxNrofCLI-RSSI-Resources-r16 INTEGER ::= 64 -- Maximum number of CLI-RSSI resources for UE +maxNrofCLI-RSSI-Resources-r16-1 INTEGER ::= 63 -- Maximum number of CLI-RSSI resources for UE minus 1 +maxNrofCLI-SRS-Resources-r16 INTEGER ::= 32 -- Maximum number of SRS resources for CLI measurement for UE +maxCLI-Report-r16 INTEGER ::= 8 +maxNrofConfiguredGrantConfig-r16 INTEGER ::= 12 -- Maximum number of configured grant configurations per BWP +maxNrofConfiguredGrantConfig-r16-1 INTEGER ::= 11 -- Maximum number of configured grant configurations per BWP minus 1 +maxNrofCG-Type2DeactivationState INTEGER ::= 16 -- Maximum number of deactivation state for type 2 configured grants per BWP +maxNrofConfiguredGrantConfigMAC-r16 INTEGER ::= 32 -- Maximum number of configured grant configurations per MAC entity +maxNrofConfiguredGrantConfigMAC-r16-1 INTEGER ::= 31 -- Maximum number of configured grant configurations per MAC entity minus 1 +maxNrofSPS-Config-r16 INTEGER ::= 8 -- Maximum number of SPS configurations per BWP +maxNrofSPS-Config-r16-1 INTEGER ::= 7 -- Maximum number of SPS configurations per BWP minus 1 +maxNrofSPS-DeactivationState INTEGER ::= 16 -- Maximum number of deactivation state for SPS per BWP +maxNrofDormancyGroups INTEGER ::= 5 -- +maxNrofPUCCH-ResourceGroups-1-r16 INTEGER ::= 3 -- +maxNrofServingCellsTCI-r16 INTEGER ::= 32 -- Maximum number of serving cells in simultaneousTCI-UpdateList +maxNrofTxDC-TwoCarrier-r16 INTEGER ::= 64 -- Maximum number of UL Tx DC locations reported by the UE for 2CC uplink CA + +-- TAG-MULTIPLICITY-AND-TYPE-CONSTRAINT-DEFINITIONS-STOP + +END + +-- TAG-PC5-RRC-DEFINITIONS-START + +PC5-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + SetupRelease, + RRC-TransactionIdentifier, + SN-FieldLengthAM, + SN-FieldLengthUM, + LogicalChannelIdentity, + maxNrofSLRB-r16, + maxNrofSL-QFIs-r16, + maxNrofSL-QFIsPerDest-r16, + RSRP-Range, + SL-MeasConfig-r16, + SL-MeasId-r16, + FreqBandList, + FreqBandIndicatorNR, + maxSimultaneousBands, + maxBandComb, + maxBands, + BandParametersSidelink-r16, + RLC-ParametersSidelink-r16 + + +FROM NR-RRC-Definitions; + +-- TAG-PC5-RRC-DEFINITIONS-STOP + + +-- TAG-SBCCH-SL-BCH-MESSAGE-START + +SBCCH-SL-BCH-Message ::= SEQUENCE { + message SBCCH-SL-BCH-MessageType +} + +SBCCH-SL-BCH-MessageType::= CHOICE { + c1 CHOICE { + masterInformationBlockSidelink MasterInformationBlockSidelink, + spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-SBCCH-SL-BCH-MESSAGE-STOP +-- TAG-SCCH-MESSAGE-START + +SCCH-Message ::= SEQUENCE { + message SCCH-MessageType +} + +SCCH-MessageType ::= CHOICE { + c1 CHOICE { + measurementReportSidelink MeasurementReportSidelink, + rrcReconfigurationSidelink RRCReconfigurationSidelink, + rrcReconfigurationCompleteSidelink RRCReconfigurationCompleteSidelink, + rrcReconfigurationFailureSidelink RRCReconfigurationFailureSidelink, + ueCapabilityEnquirySidelink UECapabilityEnquirySidelink, + ueCapabilityInformationSidelink UECapabilityInformationSidelink, + spare2 NULL, spare1 NULL + }, + messageClassExtension SEQUENCE {} +} + +-- TAG-SCCH-MESSAGE-STOP +-- TAG-MASTERINFORMATIONBLOCKSIDELINK-START + +MasterInformationBlockSidelink ::= SEQUENCE { + sl-TDD-Config-r16 BIT STRING (SIZE (12)), + inCoverage-r16 BOOLEAN, + directFrameNumber-r16 BIT STRING (SIZE (10)), + slotIndex-r16 BIT STRING (SIZE (7)), + reservedBits-r16 BIT STRING (SIZE (2)) +} + +-- TAG-MASTERINFORMATIONBLOCKSIDELINK-STOP +-- TAG-MEASUREMENTREPORTSIDELINK-START + +MeasurementReportSidelink ::= SEQUENCE { + criticalExtensions CHOICE { + measurementReportSidelink-r16 MeasurementReportSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementReportSidelink-IEs-r16 ::= SEQUENCE { + sl-measResults-r16 SL-MeasResults-r16, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +SL-MeasResults-r16 ::= SEQUENCE { + sl-MeasId-r16 SL-MeasId-r16, + sl-MeasResult-r16 SL-MeasResult-r16, + ... +} + +SL-MeasResult-r16 ::= SEQUENCE { + sl-ResultDMRS-r16 SL-MeasQuantityResult-r16 OPTIONAL, + ... +} + +SL-MeasQuantityResult-r16 ::= SEQUENCE { + sl-RSRP-r16 RSRP-Range OPTIONAL, + ... +} + +-- TAG-MEASUREMENTREPORTSIDELINK-STOP +-- TAG-RRCRECONFIGURATIONSIDELINK-START + +RRCReconfigurationSidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationSidelink-r16 RRCReconfigurationSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationSidelink-IEs-r16 ::= SEQUENCE { + slrb-ConfigToAddModList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SLRB-Config-r16 OPTIONAL, -- Need N + slrb-ConfigToReleaseList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SLRB-PC5-ConfigIndex-r16 OPTIONAL, -- Need N + sl-MeasConfig-r16 SetupRelease {SL-MeasConfig-r16} OPTIONAL, -- Need M + sl-CSI-RS-Config-r16 SetupRelease {SL-CSI-RS-Config-r16} OPTIONAL, -- Need M + sl-ResetConfig-r16 ENUMERATED {true} OPTIONAL, -- Need N + sl-LatencyBoundCSI-Report-r16 INTEGER (3..160) OPTIONAL, -- Need M + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +SLRB-Config-r16::= SEQUENCE { + slrb-PC5-ConfigIndex-r16 SLRB-PC5-ConfigIndex-r16, + sl-SDAP-ConfigPC5-r16 SL-SDAP-ConfigPC5-r16 OPTIONAL, -- Need M + sl-PDCP-ConfigPC5-r16 SL-PDCP-ConfigPC5-r16 OPTIONAL, -- Need M + sl-RLC-ConfigPC5-r16 SL-RLC-ConfigPC5-r16 OPTIONAL, -- Need M + sl-MAC-LogicalChannelConfigPC5-r16 SL-LogicalChannelConfigPC5-r16 OPTIONAL, -- Need M + ... +} + +SLRB-PC5-ConfigIndex-r16 ::= INTEGER (1..maxNrofSLRB-r16) + +SL-SDAP-ConfigPC5-r16 ::= SEQUENCE { + sl-MappedQoS-FlowsToAddList-r16 SEQUENCE (SIZE (1.. maxNrofSL-QFIsPerDest-r16)) OF SL-PQFI-r16 OPTIONAL, -- Need N + sl-MappedQoS-FlowsToReleaseList-r16 SEQUENCE (SIZE (1.. maxNrofSL-QFIsPerDest-r16)) OF SL-PQFI-r16 OPTIONAL, -- Need N + sl-SDAP-Header-r16 ENUMERATED {present, absent}, + ... +} + +SL-PDCP-ConfigPC5-r16 ::= SEQUENCE { + sl-PDCP-SN-Size-r16 ENUMERATED {len12bits, len18bits} OPTIONAL, -- Need M + sl-OutOfOrderDelivery-r16 ENUMERATED { true } OPTIONAL, -- Need R + ... +} + +SL-RLC-ConfigPC5-r16 ::= CHOICE { + sl-AM-RLC-r16 SEQUENCE { + sl-SN-FieldLengthAM-r16 SN-FieldLengthAM OPTIONAL, -- Need M + ... + }, + sl-UM-Bi-Directional-RLC-r16 SEQUENCE { + sl-SN-FieldLengthUM-r16 SN-FieldLengthUM OPTIONAL, -- Need M + ... + }, + sl-UM-Uni-Directional-RLC-r16 SEQUENCE { + sl-SN-FieldLengthUM-r16 SN-FieldLengthUM OPTIONAL, -- Need M + ... + } +} + +SL-LogicalChannelConfigPC5-r16 ::= SEQUENCE { + sl-LogicalChannelIdentity-r16 LogicalChannelIdentity, + ... +} + +SL-PQFI-r16 ::= INTEGER (1..64) + +SL-CSI-RS-Config-r16 ::= SEQUENCE { + sl-CSI-RS-FreqAllocation-r16 CHOICE { + sl-OneAntennaPort-r16 BIT STRING (SIZE (12)), + sl-TwoAntennaPort-r16 BIT STRING (SIZE (6)) + } OPTIONAL, -- Need M + sl-CSI-RS-FirstSymbol-r16 INTEGER (3..12) OPTIONAL, -- Need M + ... +} + +-- TAG-RRCRECONFIGURATIONSIDELINK-STOP +-- TAG-RRCRECONFIGURATIONCOMPLETESIDELINK-START + +RRCReconfigurationCompleteSidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationCompleteSidelink-r16 RRCReconfigurationCompleteSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationCompleteSidelink-IEs-r16 ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRECONFIGURATIONCOMPLETESIDELINK-STOP +-- TAG-RRCRECONFIGURATIONFAILURESIDELINK-START + +RRCReconfigurationFailureSidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + rrcReconfigurationFailureSidelink-r16 RRCReconfigurationFailureSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +RRCReconfigurationFailureSidelink-IEs-r16 ::= SEQUENCE { + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-RRCRECONFIGURATIONFAILURESIDELINK-STOP +-- TAG-UECAPABILITYENQUIRYSIDELINK-START + +UECapabilityEnquirySidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityEnquirySidelink-r16 UECapabilityEnquirySidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityEnquirySidelink-IEs-r16 ::= SEQUENCE { + frequencyBandListFilterSidelink-r16 FreqBandList OPTIONAL, -- Need N + ue-CapabilityInformationSidelink-r16 OCTET STRING OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +-- TAG-UECAPABILITYENQUIRYSIDELINK-STOP +-- TAG-UECAPABILITYINFORMATIONSIDELINK-START + +UECapabilityInformationSidelink ::= SEQUENCE { + rrc-TransactionIdentifier-r16 RRC-TransactionIdentifier, + criticalExtensions CHOICE { + ueCapabilityInformationSidelink-r16 UECapabilityInformationSidelink-IEs-r16, + criticalExtensionsFuture SEQUENCE {} + } +} + +UECapabilityInformationSidelink-IEs-r16 ::= SEQUENCE { + accessStratumReleaseSidelink-r16 AccessStratumReleaseSidelink-r16, + pdcp-ParametersSidelink-r16 PDCP-ParametersSidelink-r16 OPTIONAL, + rlc-ParametersSidelink-r16 RLC-ParametersSidelink-r16 OPTIONAL, + supportedBandCombinationListSidelinkNR-r16 BandCombinationListSidelinkNR-r16 OPTIONAL, + supportedBandListSidelink-r16 SEQUENCE (SIZE (1..maxBands)) OF BandSidelinkPC5-r16 OPTIONAL, + appliedFreqBandListFilter-r16 FreqBandList OPTIONAL, + lateNonCriticalExtension OCTET STRING OPTIONAL, + nonCriticalExtension SEQUENCE{} OPTIONAL +} + +AccessStratumReleaseSidelink-r16 ::= ENUMERATED { rel16, spare7, spare6, spare5, spare4, spare3, spare2, spare1, ... } + +PDCP-ParametersSidelink-r16 ::= SEQUENCE { + outOfOrderDeliverySidelink-r16 ENUMERATED {supported} OPTIONAL, + ... +} + +BandCombinationListSidelinkNR-r16 ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationParametersSidelinkNR-r16 + +BandCombinationParametersSidelinkNR-r16 ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandParametersSidelink-r16 + +BandSidelinkPC5-r16 ::= SEQUENCE { + freqBandSidelink-r16 FreqBandIndicatorNR, + --15-1 + sl-Reception-r16 SEQUENCE { + harq-RxProcessSidelink-r16 ENUMERATED {n16, n24, n32, n64}, + pscch-RxSidelink-r16 ENUMERATED {value1, value2}, + scs-CP-PatternRxSidelink-r16 CHOICE { + fr1-r16 SEQUENCE { + scs-15kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-30kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + }, + fr2-r16 SEQUENCE { + scs-60kHz-r16 BIT STRING (SIZE (16)) OPTIONAL, + scs-120kHz-r16 BIT STRING (SIZE (16)) OPTIONAL + } + } OPTIONAL, + extendedCP-RxSidelink-r16 ENUMERATED {supported} OPTIONAL + } OPTIONAL, + --15-10 + sl-Tx-256QAM-r16 ENUMERATED {supported} OPTIONAL, + --15-12 + lowSE-64QAM-MCS-TableSidelink-r16 ENUMERATED {supported} OPTIONAL, + ..., + [[ + --15-14 + csi-ReportSidelink-r16 SEQUENCE { + csi-RS-PortsSidelink-r16 ENUMERATED {p1, p2} + } OPTIONAL, + --15-19 + rankTwoReception-r16 ENUMERATED {supported} OPTIONAL, + --15-23 + sl-openLoopPC-RSRP-ReportSidelink-r16 ENUMERATED {supported} OPTIONAL, + --13-1 + sl-Rx-256QAM-r16 ENUMERATED {supported} OPTIONAL + ]] +} + +-- TAG-UECAPABILITYINFORMATIONSIDELINK-STOP + +END + +-- NR-UE-VARIABLES-START +NR-UE-Variables DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + ARFCN-ValueNR, + CellIdentity, + EUTRA-PhysCellId, + MeasId, + MeasIdToAddModList, + MeasIdleCarrierEUTRA-r16, + MeasIdleCarrierNR-r16, + MeasResultIdleEUTRA-r16, + MeasResultIdleNR-r16, + MeasObjectToAddModList, + PhysCellId, + RNTI-Value, + ReportConfigToAddModList, + RSRP-Range, + SL-MeasId-r16, + SL-MeasIdList-r16, + SL-MeasObjectList-r16, + SL-ReportConfigList-r16, + SL-QuantityConfig-r16, + Tx-PoolMeasList-r16, + QuantityConfig, + maxNrofCellMeas, + maxNrofMeasId, + maxFreqIdle-r16, + PhysCellIdUTRA-FDD-r16, + ValidityAreaList-r16, + CondReconfigToAddModList-r16, + ConnEstFailReport-r16, + LoggingDuration-r16, + LoggingInterval-r16, + LogMeasInfoList-r16, + LogMeasInfo-r16, + RA-Report-r16, + RLF-Report-r16, + TraceReference-r16, + WLAN-Identifiers-r16, + WLAN-NameList-r16, + BT-NameList-r16, + PLMN-Identity, + maxPLMN, + RA-ReportList-r16, + VisitedCellInfoList-r16, + AbsoluteTimeInfo-r16, + LoggedEventTriggerConfig-r16, + LoggedPeriodicalReportConfig-r16, + Sensor-NameList-r16, + PLMN-IdentityList2-r16, + AreaConfiguration-r16, + maxNrofSL-MeasId-r16, + maxNrofFreqSL-r16, + maxNrofCLI-RSSI-Resources-r16, + maxNrofCLI-SRS-Resources-r16, + RSSI-ResourceId-r16, + SRS-ResourceId +FROM NR-RRC-Definitions; + +-- NR-UE-VARIABLES-STOP +-- TAG-VARCONDITIONALRECONFIG-START + +VarConditionalReconfig ::= SEQUENCE { + condReconfigList CondReconfigToAddModList-r16 OPTIONAL +} + + +-- TAG-VARCONDITIONALRECONFIG-STOP +-- TAG-VARCONNESTFAILREPORT-START + +VarConnEstFailReport-r16 ::= SEQUENCE { + connEstFailReport-r16 ConnEstFailReport-r16, + plmn-Identity-r16 PLMN-Identity +} + +-- TAG-VARCONNESTFAILREPORT-STOP +-- TAG-VARLOGMEASCONFIG-START + +VarLogMeasConfig-r16-IEs ::= SEQUENCE { + areaConfiguration-r16 AreaConfiguration-r16 OPTIONAL, + bt-NameList-r16 BT-NameList-r16 OPTIONAL, + wlan-NameList-r16 WLAN-NameList-r16 OPTIONAL, + sensor-NameList-r16 Sensor-NameList-r16 OPTIONAL, + loggingDuration-r16 LoggingDuration-r16, + reportType CHOICE { + periodical LoggedPeriodicalReportConfig-r16, + eventTriggered LoggedEventTriggerConfig-r16 + } +} +-- TAG-VARLOGMEASCONFIG-STOP +-- TAG-VARLOGMEASREPORT-START + +VarLogMeasReport-r16 ::= SEQUENCE { + absoluteTimeInfo-r16 AbsoluteTimeInfo-r16, + traceReference-r16 TraceReference-r16, + traceRecordingSessionRef-r16 OCTET STRING (SIZE (2)), + tce-Id-r16 OCTET STRING (SIZE (1)), + logMeasInfoList-r16 LogMeasInfoList-r16, + plmn-IdentityList-r16 PLMN-IdentityList2-r16 +} + +-- TAG-VARLOGMEASREPORT-STOP +-- TAG-VARMEASCONFIG-START + +VarMeasConfig ::= SEQUENCE { + -- Measurement identities + measIdList MeasIdToAddModList OPTIONAL, + -- Measurement objects + measObjectList MeasObjectToAddModList OPTIONAL, + -- Reporting configurations + reportConfigList ReportConfigToAddModList OPTIONAL, + -- Other parameters + quantityConfig QuantityConfig OPTIONAL, + s-MeasureConfig CHOICE { + ssb-RSRP RSRP-Range, + csi-RSRP RSRP-Range + } OPTIONAL + +} + +-- TAG-VARMEASCONFIG-STOP +-- TAG-VARMEASCONFIGSL-START + +VarMeasConfigSL-r16 ::= SEQUENCE { + -- NR sidelink measurement identities + sl-MeasIdList-r16 SL-MeasIdList-r16 OPTIONAL, + -- NR sidelink measurement objects + sl-MeasObjectList-r16 SL-MeasObjectList-r16 OPTIONAL, + -- NR sidelink reporting configurations + sl-reportConfigList-r16 SL-ReportConfigList-r16 OPTIONAL, + -- Other parameters + sl-QuantityConfig-r16 SL-QuantityConfig-r16 OPTIONAL +} + +-- TAG-VARMEASCONFIGSL-STOP +-- TAG-VARMEASIDLECONFIG-START + +VarMeasIdleConfig-r16 ::= SEQUENCE { + measIdleCarrierListNR-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierNR-r16 OPTIONAL, + measIdleCarrierListEUTRA-r16 SEQUENCE (SIZE (1..maxFreqIdle-r16)) OF MeasIdleCarrierEUTRA-r16 OPTIONAL, + measIdleDuration-r16 ENUMERATED {sec10, sec30, sec60, sec120, sec180, sec240, sec300, spare}, + validityAreaList-r16 ValidityAreaList-r16 OPTIONAL +} + +-- TAG-VARMEASIDLECONFIG-STOP +-- TAG-VARMEASIDLEREPORT-START + +VarMeasIdleReport-r16 ::= SEQUENCE { + measReportIdleNR-r16 MeasResultIdleNR-r16 OPTIONAL, + measReportIdleEUTRA-r16 MeasResultIdleEUTRA-r16 OPTIONAL +} + +-- TAG-VARMEASIDLEREPORT-STOP +-- TAG-VARMEASREPORTLIST-START + +VarMeasReportList ::= SEQUENCE (SIZE (1..maxNrofMeasId)) OF VarMeasReport + +VarMeasReport ::= SEQUENCE { + -- List of measurement that have been triggered + measId MeasId, + cellsTriggeredList CellsTriggeredList OPTIONAL, + numberOfReportsSent INTEGER, + cli-TriggeredList-r16 CLI-TriggeredList-r16 OPTIONAL, + tx-PoolMeasToAddModListNR-r16 Tx-PoolMeasList-r16 OPTIONAL +} + +CellsTriggeredList ::= SEQUENCE (SIZE (1..maxNrofCellMeas)) OF CHOICE { + physCellId PhysCellId, + physCellIdEUTRA EUTRA-PhysCellId, + physCellIdUTRA-FDD-r16 PhysCellIdUTRA-FDD-r16 + } + +CLI-TriggeredList-r16 ::= CHOICE { + srs-RSRP-TriggeredList-r16 SRS-RSRP-TriggeredList-r16, + cli-RSSI-TriggeredList-r16 CLI-RSSI-TriggeredList-r16 + } + +SRS-RSRP-TriggeredList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-SRS-Resources-r16)) OF SRS-ResourceId + +CLI-RSSI-TriggeredList-r16 ::= SEQUENCE (SIZE (1.. maxNrofCLI-RSSI-Resources-r16)) OF RSSI-ResourceId-r16 + +-- TAG-VARMEASREPORTLIST-STOP +-- TAG-VARMEASREPORTLISTSL-START + +VarMeasReportListSL-r16 ::= SEQUENCE (SIZE (1..maxNrofSL-MeasId-r16)) OF VarMeasReportSL-r16 + +VarMeasReportSL-r16 ::= SEQUENCE { + -- List of NR sidelink measurement that have been triggered + sl-MeasId-r16 SL-MeasId-r16, + sl-FrequencyTriggeredList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF ARFCN-ValueNR OPTIONAL, + sl-NumberOfReportsSent-r16 INTEGER +} + +-- TAG-VARMEASREPORTLISTSL-STOP +-- TAG-VARMOBILITYHISTORYREPORT-START + +VarMobilityHistoryReport-r16 ::= VisitedCellInfoList-r16 + +-- TAG-VARMOBILITYHISTORYREPORT-STOP +-- TAG-VARPENDINGRNA-UPDATE-START + +VarPendingRNA-Update ::= SEQUENCE { + pendingRNA-Update BOOLEAN OPTIONAL +} + +-- TAG-VARPENDINGRNA-UPDATE-STOP +-- TAG-VARRA-REPORT-START + +VarRA-Report-r16 ::= SEQUENCE { + ra-ReportList-r16 RA-ReportList-r16, + plmn-IdentityList-r16 PLMN-IdentityList-r16 +} + +PLMN-IdentityList-r16 ::= SEQUENCE (SIZE (1..maxPLMN)) OF PLMN-Identity + +-- TAG-VARRA-REPORT-STOP +-- TAG-VARRESUMEMAC-INPUT-START + +VarResumeMAC-Input ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellIdentity CellIdentity, + source-c-RNTI RNTI-Value + +} + +-- TAG-VARRESUMEMAC-INPUT-STOP +-- TAG-VARRLF-REPORT-START + +VarRLF-Report-r16 ::= SEQUENCE { + rlf-Report-r16 RLF-Report-r16, + plmn-IdentityList-r16 PLMN-IdentityList2-r16 +} + +-- TAG-VARRLF-REPORT-STOP +-- TAG-VARSHORTMAC-INPUT-START + +VarShortMAC-Input ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellIdentity CellIdentity, + source-c-RNTI RNTI-Value +} + +-- TAG-VARSHORTMAC-INPUT-STOP + +END + +-- TAG-NR-SIDELINK-PRECONF-DEFINITIONS-START + +NR-Sidelink-Preconf DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + SL-CBR-CommonTxConfigList-r16, + SL-FreqConfigCommon-r16, + SL-RadioBearerConfig-r16, + SL-RLC-BearerConfig-r16, + SL-EUTRA-AnchorCarrierFreqList-r16, + SL-NR-AnchorCarrierFreqList-r16, + SL-MeasConfigCommon-r16, + SL-UE-SelectedConfig-r16, + TDD-UL-DL-ConfigCommon, + maxNrofFreqSL-r16, + maxNrofSLRB-r16, + maxSL-LCID-r16 +FROM NR-RRC-Definitions; + +-- TAG-NR-SIDELINK-PRECONF-DEFINITIONS-STOP + +-- TAG-SL-PRECONFIGURATIONNR-START + +SL-PreconfigurationNR-r16 ::= SEQUENCE { + sidelinkPreconfigNR-r16 SidelinkPreconfigNR-r16, + ... +} + +SidelinkPreconfigNR-r16 ::= SEQUENCE { + sl-PreconfigFreqInfoList-r16 SEQUENCE (SIZE (1..maxNrofFreqSL-r16)) OF SL-FreqConfigCommon-r16 OPTIONAL, + sl-PreconfigNR-AnchorCarrierFreqList-r16 SL-NR-AnchorCarrierFreqList-r16 OPTIONAL, + sl-PreconfigEUTRA-AnchorCarrierFreqList-r16 SL-EUTRA-AnchorCarrierFreqList-r16 OPTIONAL, + sl-RadioBearerPreConfigList-r16 SEQUENCE (SIZE (1..maxNrofSLRB-r16)) OF SL-RadioBearerConfig-r16 OPTIONAL, + sl-RLC-BearerPreConfigList-r16 SEQUENCE (SIZE (1..maxSL-LCID-r16)) OF SL-RLC-BearerConfig-r16 OPTIONAL, + sl-MeasPreConfig-r16 SL-MeasConfigCommon-r16 OPTIONAL, + sl-OffsetDFN-r16 INTEGER (1..1000) OPTIONAL, + t400-r16 ENUMERATED{ms100, ms200, ms300, ms400, ms600, ms1000, ms1500, ms2000} OPTIONAL, + sl-MaxNumConsecutiveDTX-r16 ENUMERATED {n1, n2, n3, n4, n6, n8, n16, n32} OPTIONAL, + sl-SSB-PriorityNR-r16 INTEGER (1..8) OPTIONAL, + sl-PreconfigGeneral-r16 SL-PreconfigGeneral-r16 OPTIONAL, + sl-UE-SelectedPreConfig-r16 SL-UE-SelectedConfig-r16 OPTIONAL, + sl-CSI-Acquisition-r16 ENUMERATED {enabled} OPTIONAL, + sl-RoHC-Profiles-r16 SL-RoHC-Profiles-r16 OPTIONAL, + sl-MaxCID-r16 INTEGER (1..16383) DEFAULT 15, + ... +} + +SL-PreconfigGeneral-r16 ::= SEQUENCE { + sl-TDD-Configuration-r16 TDD-UL-DL-ConfigCommon OPTIONAL, + reservedBits-r16 BIT STRING (SIZE (2)) OPTIONAL, + ... +} + +SL-RoHC-Profiles-r16 ::= SEQUENCE { + profile0x0001-r16 BOOLEAN, + profile0x0002-r16 BOOLEAN, + profile0x0003-r16 BOOLEAN, + profile0x0004-r16 BOOLEAN, + profile0x0006-r16 BOOLEAN, + profile0x0101-r16 BOOLEAN, + profile0x0102-r16 BOOLEAN, + profile0x0103-r16 BOOLEAN, + profile0x0104-r16 BOOLEAN +} + +-- TAG-SL-PRECONFIGURATIONNR-STOP + +END + +-- TAG-NR-INTER-NODE-DEFINITIONS-START +NR-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::= + +BEGIN + +IMPORTS + ARFCN-ValueNR, + ARFCN-ValueEUTRA, + CellIdentity, + CGI-InfoEUTRA, + CGI-InfoNR, + CSI-RS-Index, + CSI-RS-CellMobility, + DRX-Config, + EUTRA-PhysCellId, + FeatureSetDownlinkPerCC-Id, + FeatureSetUplinkPerCC-Id, + FreqBandIndicatorNR, + GapConfig, + maxBandComb, + maxBands, + maxCellSFTD, + maxFeatureSetsPerBand, + maxFreqIDC-MRDC, + maxNrofCombIDC, + maxNrofPhysicalResourceBlocks, + maxNrofSCells, + maxNrofServingCells, + maxNrofServingCells-1, + maxNrofServingCellsEUTRA, + maxNrofIndexesToReport, + maxSimultaneousBands, + MeasQuantityResults, + MeasResultCellListSFTD-EUTRA, + MeasResultCellListSFTD-NR, + MeasResultList2NR, + MeasResultSCG-Failure, + MeasResultServFreqListEUTRA-SCG, + NeedForGapsInfoNR-r16, + OverheatingAssistance, + P-Max, + PhysCellId, + RadioBearerConfig, + RAN-NotificationAreaInfo, + RRCReconfiguration, + ServCellIndex, + SetupRelease, + SSB-Index, + SSB-MTC, + SSB-ToMeasure, + SS-RSSI-Measurement, + ShortMAC-I, + SubcarrierSpacing, + UEAssistanceInformation, + UE-CapabilityRAT-ContainerList, + maxNrofCLI-RSSI-Resources-r16, + maxNrofCLI-SRS-Resources-r16, + RSSI-ResourceId-r16, + SidelinkUEInformationNR-r16, + SRS-ResourceId +FROM NR-RRC-Definitions; + +-- TAG-NR-INTER-NODE-DEFINITIONS-STOP +-- TAG-HANDOVER-COMMAND-START + +HandoverCommand ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverCommand HandoverCommand-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverCommand-IEs ::= SEQUENCE { + handoverCommandMessage OCTET STRING (CONTAINING RRCReconfiguration), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-HANDOVER-COMMAND-STOP +-- TAG-HANDOVER-PREPARATION-INFORMATION-START + +HandoverPreparationInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + handoverPreparationInformation HandoverPreparationInformation-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +HandoverPreparationInformation-IEs ::= SEQUENCE { + ue-CapabilityRAT-List UE-CapabilityRAT-ContainerList, + sourceConfig AS-Config OPTIONAL, -- Cond HO + rrm-Config RRM-Config OPTIONAL, + as-Context AS-Context OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +AS-Config ::= SEQUENCE { + rrcReconfiguration OCTET STRING (CONTAINING RRCReconfiguration), + ..., + [[ + sourceRB-SN-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + sourceSCG-NR-Config OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + sourceSCG-EUTRA-Config OCTET STRING OPTIONAL + ]], + [[ + sourceSCG-Configured ENUMERATED {true} OPTIONAL + ]] + +} + +AS-Context ::= SEQUENCE { + reestablishmentInfo ReestablishmentInfo OPTIONAL, + configRestrictInfo ConfigRestrictInfoSCG OPTIONAL, + ..., + [[ ran-NotificationAreaInfo RAN-NotificationAreaInfo OPTIONAL + ]], + [[ ueAssistanceInformation OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL -- Cond HO2 + ]], + [[ + selectedBandCombinationSN BandCombinationInfoSN OPTIONAL + ]], + [[ + configRestrictInfoDAPS-r16 ConfigRestrictInfoDAPS-r16 OPTIONAL, + sidelinkUEInformationNR-r16 OCTET STRING OPTIONAL, + sidelinkUEInformationEUTRA-r16 OCTET STRING OPTIONAL, + ueAssistanceInformationEUTRA-r16 OCTET STRING OPTIONAL, + ueAssistanceInformationSCG-r16 OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL, -- Cond HO2 + needForGapsInfoNR-r16 NeedForGapsInfoNR-r16 OPTIONAL + ]], + [[ + configRestrictInfoDAPS-v1640 ConfigRestrictInfoDAPS-v1640 OPTIONAL + ]] +} + +ConfigRestrictInfoDAPS-r16 ::= SEQUENCE { + powerCoordination-r16 SEQUENCE { + p-DAPS-Source-r16 P-Max, + p-DAPS-Target-r16 P-Max, + uplinkPowerSharingDAPS-Mode-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic } + } OPTIONAL +} + +ConfigRestrictInfoDAPS-v1640 ::= SEQUENCE { + sourceFeatureSetPerDownlinkCC-r16 FeatureSetDownlinkPerCC-Id, + sourceFeatureSetPerUplinkCC-r16 FeatureSetUplinkPerCC-Id +} + +ReestablishmentInfo ::= SEQUENCE { + sourcePhysCellId PhysCellId, + targetCellShortMAC-I ShortMAC-I, + additionalReestabInfoList ReestabNCellInfoList OPTIONAL +} + +ReestabNCellInfoList ::= SEQUENCE ( SIZE (1..maxCellPrep) ) OF ReestabNCellInfo + +ReestabNCellInfo::= SEQUENCE{ + cellIdentity CellIdentity, + key-gNodeB-Star BIT STRING (SIZE (256)), + shortMAC-I ShortMAC-I +} + +RRM-Config ::= SEQUENCE { + ue-InactiveTime ENUMERATED { + s1, s2, s3, s5, s7, s10, s15, s20, + s25, s30, s40, s50, min1, min1s20, min1s40, + min2, min2s30, min3, min3s30, min4, min5, min6, + min7, min8, min9, min10, min12, min14, min17, min20, + min24, min28, min33, min38, min44, min50, hr1, + hr1min30, hr2, hr2min30, hr3, hr3min30, hr4, hr5, hr6, + hr8, hr10, hr13, hr16, hr20, day1, day1hr12, day2, + day2hr12, day3, day4, day5, day7, day10, day14, day19, + day24, day30, dayMoreThan30} OPTIONAL, + candidateCellInfoList MeasResultList2NR OPTIONAL, + ..., + [[ + candidateCellInfoListSN-EUTRA MeasResultServFreqListEUTRA-SCG OPTIONAL + ]] +} + +-- TAG-HANDOVER-PREPARATION-INFORMATION-STOP +-- TAG-CG-CONFIG-START + +CG-Config ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + cg-Config CG-Config-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +CG-Config-IEs ::= SEQUENCE { + scg-CellGroupConfig OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + scg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + configRestrictModReq ConfigRestrictModReqSCG OPTIONAL, + drx-InfoSCG DRX-Info OPTIONAL, + candidateCellInfoListSN OCTET STRING (CONTAINING MeasResultList2NR) OPTIONAL, + measConfigSN MeasConfigSN OPTIONAL, + selectedBandCombination BandCombinationInfoSN OPTIONAL, + fr-InfoListSCG FR-InfoList OPTIONAL, + candidateServingFreqListNR CandidateServingFreqListNR OPTIONAL, + nonCriticalExtension CG-Config-v1540-IEs OPTIONAL +} + +CG-Config-v1540-IEs ::= SEQUENCE { + pSCellFrequency ARFCN-ValueNR OPTIONAL, + reportCGI-RequestNR SEQUENCE { + requestedCellInfo SEQUENCE { + ssbFrequency ARFCN-ValueNR, + cellForWhichToReportCGI PhysCellId + } OPTIONAL + } OPTIONAL, + ph-InfoSCG PH-TypeListSCG OPTIONAL, + nonCriticalExtension CG-Config-v1560-IEs OPTIONAL +} + +CG-Config-v1560-IEs ::= SEQUENCE { + pSCellFrequencyEUTRA ARFCN-ValueEUTRA OPTIONAL, + scg-CellGroupConfigEUTRA OCTET STRING OPTIONAL, + candidateCellInfoListSN-EUTRA OCTET STRING OPTIONAL, + candidateServingFreqListEUTRA CandidateServingFreqListEUTRA OPTIONAL, + needForGaps ENUMERATED {true} OPTIONAL, + drx-ConfigSCG DRX-Config OPTIONAL, + reportCGI-RequestEUTRA SEQUENCE { + requestedCellInfoEUTRA SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cellForWhichToReportCGI-EUTRA EUTRA-PhysCellId + } OPTIONAL + } OPTIONAL, + nonCriticalExtension CG-Config-v1590-IEs OPTIONAL +} + +CG-Config-v1590-IEs ::= SEQUENCE { + scellFrequenciesSN-NR SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueNR OPTIONAL, + scellFrequenciesSN-EUTRA SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueEUTRA OPTIONAL, + nonCriticalExtension CG-Config-v1610-IEs OPTIONAL +} + +CG-Config-v1610-IEs ::= SEQUENCE { + drx-InfoSCG2 DRX-Info2 OPTIONAL, + nonCriticalExtension CG-Config-v1620-IEs OPTIONAL +} + +CG-Config-v1620-IEs ::= SEQUENCE { + ueAssistanceInformationSCG-r16 OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL, + nonCriticalExtension CG-Config-v1630-IEs OPTIONAL +} + +CG-Config-v1630-IEs ::= SEQUENCE { + selectedToffset-r16 T-Offset-r16 OPTIONAL, + nonCriticalExtension CG-Config-v1640-IEs OPTIONAL +} + +CG-Config-v1640-IEs ::= SEQUENCE { + servCellInfoListSCG-NR-r16 ServCellInfoListSCG-NR-r16 OPTIONAL, + servCellInfoListSCG-EUTRA-r16 ServCellInfoListSCG-EUTRA-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +ServCellInfoListSCG-NR-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCells)) OF ServCellInfoXCG-NR-r16 + +ServCellInfoXCG-NR-r16 ::= SEQUENCE { + dl-FreqInfo-NR-r16 FrequencyConfig-NR-r16 OPTIONAL, + ul-FreqInfo-NR-r16 FrequencyConfig-NR-r16 OPTIONAL, -- Cond FDD + ... +} + +FrequencyConfig-NR-r16 ::= SEQUENCE { + freqBandIndicatorNR-r16 FreqBandIndicatorNR, + carrierCenterFreq-NR-r16 ARFCN-ValueNR, + carrierBandwidth-NR-r16 INTEGER (1..maxNrofPhysicalResourceBlocks), + subcarrierSpacing-NR-r16 SubcarrierSpacing +} + +ServCellInfoListSCG-EUTRA-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCellsEUTRA)) OF ServCellInfoXCG-EUTRA-r16 + +ServCellInfoXCG-EUTRA-r16 ::= SEQUENCE { + dl-CarrierFreq-EUTRA-r16 ARFCN-ValueEUTRA OPTIONAL, + ul-CarrierFreq-EUTRA-r16 ARFCN-ValueEUTRA OPTIONAL, -- Cond FDD + transmissionBandwidth-EUTRA-r16 TransmissionBandwidth-EUTRA-r16 OPTIONAL, + ... +} + +TransmissionBandwidth-EUTRA-r16 ::= ENUMERATED {rb6, rb15, rb25, rb50, rb75, rb100} + +PH-TypeListSCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF PH-InfoSCG + +PH-InfoSCG ::= SEQUENCE { + servCellIndex ServCellIndex, + ph-Uplink PH-UplinkCarrierSCG, + ph-SupplementaryUplink PH-UplinkCarrierSCG OPTIONAL, + ... +} + +PH-UplinkCarrierSCG ::= SEQUENCE{ + ph-Type1or3 ENUMERATED {type1, type3}, + ... +} + +MeasConfigSN ::= SEQUENCE { + measuredFrequenciesSN SEQUENCE (SIZE (1..maxMeasFreqsSN)) OF NR-FreqInfo OPTIONAL, + ... +} + +NR-FreqInfo ::= SEQUENCE { + measuredFrequency ARFCN-ValueNR OPTIONAL, + ... +} + +ConfigRestrictModReqSCG ::= SEQUENCE { + requestedBC-MRDC BandCombinationInfoSN OPTIONAL, + requestedP-MaxFR1 P-Max OPTIONAL, + ..., + [[ + requestedPDCCH-BlindDetectionSCG INTEGER (1..15) OPTIONAL, + requestedP-MaxEUTRA P-Max OPTIONAL + ]], + [[ + requestedP-MaxFR2-r16 P-Max OPTIONAL, + requestedMaxInterFreqMeasIdSCG-r16 INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + requestedMaxIntraFreqMeasIdSCG-r16 INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + requestedToffset-r16 T-Offset-r16 OPTIONAL + ]] +} + +BandCombinationIndex ::= INTEGER (1..maxBandComb) + +BandCombinationInfoSN ::= SEQUENCE { + bandCombinationIndex BandCombinationIndex, + requestedFeatureSets FeatureSetEntryIndex +} + +FR-InfoList ::= SEQUENCE (SIZE (1..maxNrofServingCells-1)) OF FR-Info + +FR-Info ::= SEQUENCE { + servCellIndex ServCellIndex, + fr-Type ENUMERATED {fr1, fr2} +} + +CandidateServingFreqListNR ::= SEQUENCE (SIZE (1.. maxFreqIDC-MRDC)) OF ARFCN-ValueNR + +CandidateServingFreqListEUTRA ::= SEQUENCE (SIZE (1.. maxFreqIDC-MRDC)) OF ARFCN-ValueEUTRA + +T-Offset-r16 ::= ENUMERATED {ms0dot5, ms0dot75, ms1, ms1dot5, ms2, ms2dot5, ms3, spare1} + +-- TAG-CG-CONFIG-STOP +-- TAG-CG-CONFIG-INFO-START + +CG-ConfigInfo ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + cg-ConfigInfo CG-ConfigInfo-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +CG-ConfigInfo-IEs ::= SEQUENCE { + ue-CapabilityInfo OCTET STRING (CONTAINING UE-CapabilityRAT-ContainerList) OPTIONAL,-- Cond SN-AddMod + candidateCellInfoListMN MeasResultList2NR OPTIONAL, + candidateCellInfoListSN OCTET STRING (CONTAINING MeasResultList2NR) OPTIONAL, + measResultCellListSFTD-NR MeasResultCellListSFTD-NR OPTIONAL, + scgFailureInfo SEQUENCE { + failureType ENUMERATED { t310-Expiry, randomAccessProblem, + rlc-MaxNumRetx, synchReconfigFailure-SCG, + scg-reconfigFailure, + srb3-IntegrityFailure}, + measResultSCG OCTET STRING (CONTAINING MeasResultSCG-Failure) + } OPTIONAL, + configRestrictInfo ConfigRestrictInfoSCG OPTIONAL, + drx-InfoMCG DRX-Info OPTIONAL, + measConfigMN MeasConfigMN OPTIONAL, + sourceConfigSCG OCTET STRING (CONTAINING RRCReconfiguration) OPTIONAL, + scg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + mcg-RB-Config OCTET STRING (CONTAINING RadioBearerConfig) OPTIONAL, + mrdc-AssistanceInfo MRDC-AssistanceInfo OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1540-IEs OPTIONAL +} + +CG-ConfigInfo-v1540-IEs ::= SEQUENCE { + ph-InfoMCG PH-TypeListMCG OPTIONAL, + measResultReportCGI SEQUENCE { + ssbFrequency ARFCN-ValueNR, + cellForWhichToReportCGI PhysCellId, + cgi-Info CGI-InfoNR + } OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1560-IEs OPTIONAL +} + +CG-ConfigInfo-v1560-IEs ::= SEQUENCE { + candidateCellInfoListMN-EUTRA OCTET STRING OPTIONAL, + candidateCellInfoListSN-EUTRA OCTET STRING OPTIONAL, + sourceConfigSCG-EUTRA OCTET STRING OPTIONAL, + scgFailureInfoEUTRA SEQUENCE { + failureTypeEUTRA ENUMERATED { t313-Expiry, randomAccessProblem, + rlc-MaxNumRetx, scg-ChangeFailure}, + measResultSCG-EUTRA OCTET STRING + } OPTIONAL, + drx-ConfigMCG DRX-Config OPTIONAL, + measResultReportCGI-EUTRA SEQUENCE { + eutraFrequency ARFCN-ValueEUTRA, + cellForWhichToReportCGI-EUTRA EUTRA-PhysCellId, + cgi-InfoEUTRA CGI-InfoEUTRA + } OPTIONAL, + measResultCellListSFTD-EUTRA MeasResultCellListSFTD-EUTRA OPTIONAL, + fr-InfoListMCG FR-InfoList OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1570-IEs OPTIONAL +} + +CG-ConfigInfo-v1570-IEs ::= SEQUENCE { + sftdFrequencyList-NR SFTD-FrequencyList-NR OPTIONAL, + sftdFrequencyList-EUTRA SFTD-FrequencyList-EUTRA OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1590-IEs OPTIONAL +} + +CG-ConfigInfo-v1590-IEs ::= SEQUENCE { + servFrequenciesMN-NR SEQUENCE (SIZE (1.. maxNrofServingCells-1)) OF ARFCN-ValueNR OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1610-IEs OPTIONAL +} + +CG-ConfigInfo-v1610-IEs ::= SEQUENCE { + drx-InfoMCG2 DRX-Info2 OPTIONAL, + alignedDRX-Indication ENUMERATED {true} OPTIONAL, + scgFailureInfo-r16 SEQUENCE { + failureType-r16 ENUMERATED { scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, bh-RLF-r16, + spare4, spare3, spare2, spare1}, + measResultSCG-r16 OCTET STRING (CONTAINING MeasResultSCG-Failure) + } OPTIONAL, + scgFailureInfoEUTRA-r16 SEQUENCE { + failureTypeEUTRA-r16 ENUMERATED { scg-lbtFailure-r16, beamFailureRecoveryFailure-r16, + t312-Expiry-r16, spare5, + spare4, spare3, spare2, spare1}, + measResultSCG-EUTRA-r16 OCTET STRING + } OPTIONAL, + sidelinkUEInformationNR-r16 OCTET STRING (CONTAINING SidelinkUEInformationNR-r16) OPTIONAL, + sidelinkUEInformationEUTRA-r16 OCTET STRING OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1620-IEs OPTIONAL +} + +CG-ConfigInfo-v1620-IEs ::= SEQUENCE { + ueAssistanceInformationSourceSCG-r16 OCTET STRING (CONTAINING UEAssistanceInformation) OPTIONAL, + nonCriticalExtension CG-ConfigInfo-v1640-IEs OPTIONAL +} + +CG-ConfigInfo-v1640-IEs ::= SEQUENCE { + servCellInfoListMCG-NR-r16 ServCellInfoListMCG-NR-r16 OPTIONAL, + servCellInfoListMCG-EUTRA-r16 ServCellInfoListMCG-EUTRA-r16 OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +ServCellInfoListMCG-NR-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCells)) OF ServCellInfoXCG-NR-r16 + +ServCellInfoListMCG-EUTRA-r16 ::= SEQUENCE (SIZE (1.. maxNrofServingCellsEUTRA)) OF ServCellInfoXCG-EUTRA-r16 + +SFTD-FrequencyList-NR ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF ARFCN-ValueNR + +SFTD-FrequencyList-EUTRA ::= SEQUENCE (SIZE (1..maxCellSFTD)) OF ARFCN-ValueEUTRA + +ConfigRestrictInfoSCG ::= SEQUENCE { + allowedBC-ListMRDC BandCombinationInfoList OPTIONAL, + powerCoordination-FR1 SEQUENCE { + p-maxNR-FR1 P-Max OPTIONAL, + p-maxEUTRA P-Max OPTIONAL, + p-maxUE-FR1 P-Max OPTIONAL + } OPTIONAL, + servCellIndexRangeSCG SEQUENCE { + lowBound ServCellIndex, + upBound ServCellIndex + } OPTIONAL, -- Cond SN-AddMod + maxMeasFreqsSCG INTEGER(1..maxMeasFreqsMN) OPTIONAL, + dummy INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + ..., + [[ + selectedBandEntriesMNList SEQUENCE (SIZE (1..maxBandComb)) OF SelectedBandEntriesMN OPTIONAL, + pdcch-BlindDetectionSCG INTEGER (1..15) OPTIONAL, + maxNumberROHC-ContextSessionsSN INTEGER(0.. 16384) OPTIONAL + ]], + [[ + maxIntraFreqMeasIdentitiesSCG INTEGER(1..maxMeasIdentitiesMN) OPTIONAL, + maxInterFreqMeasIdentitiesSCG INTEGER(1..maxMeasIdentitiesMN) OPTIONAL + ]], + [[ + p-maxNR-FR1-MCG-r16 P-Max OPTIONAL, + powerCoordination-FR2-r16 SEQUENCE { + p-maxNR-FR2-MCG-r16 P-Max OPTIONAL, + p-maxNR-FR2-SCG-r16 P-Max OPTIONAL, + p-maxUE-FR2-r16 P-Max OPTIONAL + } OPTIONAL, + nrdc-PC-mode-FR1-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, + nrdc-PC-mode-FR2-r16 ENUMERATED {semi-static-mode1, semi-static-mode2, dynamic} OPTIONAL, + maxMeasSRS-ResourceSCG-r16 INTEGER(0..maxNrofCLI-SRS-Resources-r16) OPTIONAL, + maxMeasCLI-ResourceSCG-r16 INTEGER(0..maxNrofCLI-RSSI-Resources-r16) OPTIONAL, + maxNumberEHC-ContextsSN-r16 INTEGER(0..65536) OPTIONAL, + allowedReducedConfigForOverheating-r16 OverheatingAssistance OPTIONAL, + maxToffset-r16 T-Offset-r16 OPTIONAL + ]] +} + +SelectedBandEntriesMN ::= SEQUENCE (SIZE (1..maxSimultaneousBands)) OF BandEntryIndex + +BandEntryIndex ::= INTEGER (0.. maxNrofServingCells) + +PH-TypeListMCG ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF PH-InfoMCG + +PH-InfoMCG ::= SEQUENCE { + servCellIndex ServCellIndex, + ph-Uplink PH-UplinkCarrierMCG, + ph-SupplementaryUplink PH-UplinkCarrierMCG OPTIONAL, + ... +} + +PH-UplinkCarrierMCG ::= SEQUENCE{ + ph-Type1or3 ENUMERATED {type1, type3}, + ... +} + +BandCombinationInfoList ::= SEQUENCE (SIZE (1..maxBandComb)) OF BandCombinationInfo + +BandCombinationInfo ::= SEQUENCE { + bandCombinationIndex BandCombinationIndex, + allowedFeatureSetsList SEQUENCE (SIZE (1..maxFeatureSetsPerBand)) OF FeatureSetEntryIndex +} + +FeatureSetEntryIndex ::= INTEGER (1.. maxFeatureSetsPerBand) + +DRX-Info ::= SEQUENCE { + drx-LongCycleStartOffset CHOICE { + ms10 INTEGER(0..9), + ms20 INTEGER(0..19), + ms32 INTEGER(0..31), + ms40 INTEGER(0..39), + ms60 INTEGER(0..59), + ms64 INTEGER(0..63), + ms70 INTEGER(0..69), + ms80 INTEGER(0..79), + ms128 INTEGER(0..127), + ms160 INTEGER(0..159), + ms256 INTEGER(0..255), + ms320 INTEGER(0..319), + ms512 INTEGER(0..511), + ms640 INTEGER(0..639), + ms1024 INTEGER(0..1023), + ms1280 INTEGER(0..1279), + ms2048 INTEGER(0..2047), + ms2560 INTEGER(0..2559), + ms5120 INTEGER(0..5119), + ms10240 INTEGER(0..10239) + }, + shortDRX SEQUENCE { + drx-ShortCycle ENUMERATED { + ms2, ms3, ms4, ms5, ms6, ms7, ms8, ms10, ms14, ms16, ms20, ms30, ms32, + ms35, ms40, ms64, ms80, ms128, ms160, ms256, ms320, ms512, ms640, spare9, + spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 }, + drx-ShortCycleTimer INTEGER (1..16) + } OPTIONAL +} + +DRX-Info2 ::= SEQUENCE { + drx-onDurationTimer CHOICE { + subMilliSeconds INTEGER (1..31), + milliSeconds ENUMERATED { + ms1, ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, ms40, ms50, ms60, + ms80, ms100, ms200, ms300, ms400, ms500, ms600, ms800, ms1000, ms1200, + ms1600, spare8, spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + } +} + +MeasConfigMN ::= SEQUENCE { + measuredFrequenciesMN SEQUENCE (SIZE (1..maxMeasFreqsMN)) OF NR-FreqInfo OPTIONAL, + measGapConfig SetupRelease { GapConfig } OPTIONAL, + gapPurpose ENUMERATED {perUE, perFR1} OPTIONAL, + ..., + [[ + measGapConfigFR2 SetupRelease { GapConfig } OPTIONAL + ]] + +} + +MRDC-AssistanceInfo ::= SEQUENCE { + affectedCarrierFreqCombInfoListMRDC SEQUENCE (SIZE (1..maxNrofCombIDC)) OF AffectedCarrierFreqCombInfoMRDC, + ..., + [[ + overheatingAssistanceSCG-r16 OCTET STRING (CONTAINING OverheatingAssistance) OPTIONAL + ]] +} + +AffectedCarrierFreqCombInfoMRDC ::= SEQUENCE { + victimSystemType VictimSystemType, + interferenceDirectionMRDC ENUMERATED {eutra-nr, nr, other, utra-nr-other, nr-other, spare3, spare2, spare1}, + affectedCarrierFreqCombMRDC SEQUENCE { + affectedCarrierFreqCombEUTRA AffectedCarrierFreqCombEUTRA OPTIONAL, + affectedCarrierFreqCombNR AffectedCarrierFreqCombNR + } OPTIONAL +} + +VictimSystemType ::= SEQUENCE { + gps ENUMERATED {true} OPTIONAL, + glonass ENUMERATED {true} OPTIONAL, + bds ENUMERATED {true} OPTIONAL, + galileo ENUMERATED {true} OPTIONAL, + wlan ENUMERATED {true} OPTIONAL, + bluetooth ENUMERATED {true} OPTIONAL +} + +AffectedCarrierFreqCombEUTRA ::= SEQUENCE (SIZE (1..maxNrofServingCellsEUTRA)) OF ARFCN-ValueEUTRA + +AffectedCarrierFreqCombNR ::= SEQUENCE (SIZE (1..maxNrofServingCells)) OF ARFCN-ValueNR + +-- TAG-CG-CONFIG-INFO-STOP +-- TAG-MEASUREMENT-TIMING-CONFIGURATION-START + +MeasurementTimingConfiguration ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + measTimingConf MeasurementTimingConfiguration-IEs, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +MeasurementTimingConfiguration-IEs ::= SEQUENCE { + measTiming MeasTimingList OPTIONAL, + nonCriticalExtension MeasurementTimingConfiguration-v1550-IEs OPTIONAL +} + +MeasurementTimingConfiguration-v1550-IEs ::= SEQUENCE { + campOnFirstSSB BOOLEAN, + psCellOnlyOnFirstSSB BOOLEAN, + nonCriticalExtension MeasurementTimingConfiguration-v1610-IEs OPTIONAL +} + +MeasurementTimingConfiguration-v1610-IEs ::= SEQUENCE { + csi-RS-Config-r16 SEQUENCE { + csi-RS-SubcarrierSpacing-r16 SubcarrierSpacing, + csi-RS-CellMobility-r16 CSI-RS-CellMobility, + refSSBFreq-r16 ARFCN-ValueNR + }, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +MeasTimingList ::= SEQUENCE (SIZE (1..maxMeasFreqsMN)) OF MeasTiming + +MeasTiming ::= SEQUENCE { + frequencyAndTiming SEQUENCE { + carrierFreq ARFCN-ValueNR, + ssbSubcarrierSpacing SubcarrierSpacing, + ssb-MeasurementTimingConfiguration SSB-MTC, + ss-RSSI-Measurement SS-RSSI-Measurement OPTIONAL + } OPTIONAL, + ..., + [[ + ssb-ToMeasure SSB-ToMeasure OPTIONAL, + physCellId PhysCellId OPTIONAL + ]] +} + +-- TAG-MEASUREMENT-TIMING-CONFIGURATION-STOP +-- TAG-UE-RADIO-PAGING-INFORMATION-START + +UERadioPagingInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioPagingInformation UERadioPagingInformation-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioPagingInformation-IEs ::= SEQUENCE { + supportedBandListNRForPaging SEQUENCE (SIZE (1..maxBands)) OF FreqBandIndicatorNR OPTIONAL, + nonCriticalExtension SEQUENCE {} OPTIONAL +} + + +-- TAG-UE-RADIO-PAGING-INFORMATION-STOP +-- TAG-UE-RADIO-ACCESS-CAPABILITY-INFORMATION-START + +UERadioAccessCapabilityInformation ::= SEQUENCE { + criticalExtensions CHOICE { + c1 CHOICE{ + ueRadioAccessCapabilityInformation UERadioAccessCapabilityInformation-IEs, + spare7 NULL, + spare6 NULL, spare5 NULL, spare4 NULL, + spare3 NULL, spare2 NULL, spare1 NULL + }, + criticalExtensionsFuture SEQUENCE {} + } +} + +UERadioAccessCapabilityInformation-IEs ::= SEQUENCE { + ue-RadioAccessCapabilityInfo OCTET STRING (CONTAINING UE-CapabilityRAT-ContainerList), + nonCriticalExtension SEQUENCE {} OPTIONAL +} + +-- TAG-UE-RADIO-ACCESS-CAPABILITY-INFORMATION-STOP +-- TAG-NR-MULTIPLICITY-AND-CONSTRAINTS-START + +maxMeasFreqsMN INTEGER ::= 32 -- Maximum number of MN-configured measurement frequencies +maxMeasFreqsSN INTEGER ::= 32 -- Maximum number of SN-configured measurement frequencies +maxMeasIdentitiesMN INTEGER ::= 62 -- Maximum number of measurement identities that a UE can be configured with +maxCellPrep INTEGER ::= 32 -- Maximum number of cells prepared for handover + +-- TAG-NR-MULTIPLICITY-AND-CONSTRAINTS-STOP +-- TAG-NR-INTER-NODE-DEFINITIONS-END-START + +END + +-- TAG-NR-INTER-NODE-DEFINITIONS-END-STOP From 7043f64da38abd4110860692a29821d272a0c777 Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Fri, 16 Jul 2021 13:17:38 +0200 Subject: [PATCH 122/185] Fixes of compilation errors after ASN update --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 2 +- openair2/RRC/NR/rrc_gNB_reconfig.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 5d9126ad69..03c23264a7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -157,7 +157,7 @@ void init_RA(module_id_t mod_id, } if (nr_rach_ConfigCommon->ext1) { - if (nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity){ + if (nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity_r16){ LOG_D(MAC, "In %s:%d: Missing implementation for Access Identity initialization procedures\n", __FUNCTION__, __LINE__); } } diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index e983627b56..e064138eee 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -1279,7 +1279,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->sCellDeactivationTimer=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->tag_Id=0; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->dummy=NULL; + secondaryCellGroup->spCellConfig->spCellConfigDedicated->dummy1=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->pathlossReferenceLinking=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->servingCellMO=NULL; From 85b8f78d71cb6a5b9897a3952291fba88022afbd Mon Sep 17 00:00:00 2001 From: Gokul Srinivasan Date: Tue, 3 Aug 2021 17:57:11 +0530 Subject: [PATCH 123/185] process ID overflow bugfix --- executables/nr-gnb.c | 2 +- nfapi/oai_integration/nfapi_pnf.c | 4 +- nfapi/oai_integration/nfapi_vnf.c | 4 +- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 256 ++++++--------- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 12 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 296 ++++-------------- .../PHY/LTE_UE_TRANSPORT/dlsch_decoding.c | 10 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 4 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 11 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 5 +- 10 files changed, 171 insertions(+), 433 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 166ebd69b6..beda127cfd 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -151,7 +151,7 @@ void rx_func(void *param) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick //LOG_D(PHY, "oai_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); start_meas(&nfapi_meas); - oai_slot_ind(frame_tx, slot_tx); + oai_slot_ind(frame_rx, slot_rx); stop_meas(&nfapi_meas); /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 0783aa26b3..da8912e6a9 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1253,8 +1253,8 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) { nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu = &dl_tti_pdu_list[i].pdsch_pdu; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15_pdu = &pdsch_pdu->pdsch_pdu_rel15; - //nfapi_nr_tx_data_request_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; - nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][0]; + //nfapi_nr_tx_data_request_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; + nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; if (tx_data != NULL) { int UE_id = find_nr_dlsch(rel15_pdu->rnti,gNB,SEARCH_EXIST_OR_FREE); diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index e86c932483..1bc2f70d93 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -1620,8 +1620,8 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { nfapi_setmode(NFAPI_MODE_VNF); memset(&vnf, 0, sizeof(vnf)); memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); - vnf.p7_vnfs[0].timing_window = 32; - vnf.p7_vnfs[0].periodic_timing_enabled = 1; + vnf.p7_vnfs[0].timing_window = 30; + vnf.p7_vnfs[0].periodic_timing_enabled = 0; vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; vnf.p7_vnfs[0].periodic_timing_period = 10; vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 8786e9e53c..0b75d3c7ec 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -156,17 +156,16 @@ nfapi_dl_config_request_t* allocate_nfapi_dl_config_request(pnf_p7_t* pnf_p7) void deallocate_nfapi_dl_tti_request(nfapi_nr_dl_tti_request_t* req, pnf_p7_t* pnf_p7) { //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->dl_config_request_body.dl_config_pdu_list); - /* - if(pnf_p7->_public.codec_config.deallocate) - { - //nfapi_nr_dl_tti_request_pdu_t *temp = &req->dl_tti_pdu_list; - (pnf_p7->_public.codec_config.deallocate)(req); - } - else - { - free(req); - } -*/ + + // if(pnf_p7->_public.codec_config.deallocate) + // { + // (pnf_p7->_public.codec_config.deallocate)(req); + // } + // else + // { + // free(req); + // } + pnf_p7_free(pnf_p7, req); } @@ -915,14 +914,13 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t slot) -{ +{ + //This function is aligned with rx sfn/slot + // We could either send an event to the p7 thread have have it run the // subframe or we could handle it here and lock access to the subframe // buffers. If we do it on the p7 thread then we run the risk of blocking // on the udp send. - // - // todo : start a timer to give us more of the 1 ms tick before send back - // the frame // todo : consider a more efficent lock mechasium //uint16_t NUM_SLOTS = 20;//10* 2^mu @@ -935,21 +933,21 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl // save the curren time, sfn and slot pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); - pnf_p7->sfn = sfn; - - pnf_p7->slot = slot; - - - + slot_ahead = 6; uint32_t sfn_slot_tx = sfnslot_add_slot(sfn, slot, slot_ahead); - uint16_t sfn_tx = sfn_slot_tx>>6; - uint16_t slot_tx = sfn_slot_tx & 0X3F; + uint16_t sfn_tx = NFAPI_SFNSLOT2SFN(sfn_slot_tx); + uint8_t slot_tx = NFAPI_SFNSLOT2SLOT(sfn_slot_tx); - // uint32_t tx_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); - uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); + //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. + pnf_p7->sfn = sfn_tx; + pnf_p7->slot = slot_tx; - //uint32_t tx_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn_slot_tx); + uint32_t slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); + uint8_t buffer_index_rx = slot_dec % 20; + + uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(sfn_tx,slot_tx); + uint8_t buffer_index_tx = tx_slot_dec % 20; // If the subframe_buffer has been configured if(pnf_p7->_public.slot_buffer_size!= 0) // for now value is same as sf_buffer_size @@ -976,28 +974,20 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl pnf_p7->slot_shift = 0; } - uint32_t slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); - uint8_t buffer_index = slot_dec % pnf_p7->_public.slot_buffer_size; + nfapi_pnf_p7_slot_buffer_t* rx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_rx]); - nfapi_pnf_p7_slot_buffer_t* slot_buffer = &(pnf_p7->slot_buffer[buffer_index]); - // see where the PNF_P7 slot buffer its getting filled - - uint8_t tx_buffer_index = tx_slot_dec % pnf_p7->_public.slot_buffer_size; - nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[tx_buffer_index]); + nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d slot_buffer->sfn_sf:%d tx_slot_buffer->sfn_slot:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] " "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", __FUNCTION__, pnf_p7->slot_shift, - NFAPI_SFNSLOT2DEC(slot_buffer->sfn, slot_buffer->slot), + NFAPI_SFNSLOT2DEC(rx_slot_buffer->sfn, rx_slot_buffer->slot), NFAPI_SFNSLOT2DEC(tx_slot_buffer->sfn, tx_slot_buffer->slot), - slot_dec, buffer_index, slot_buffer->dl_tti_req, slot_buffer->tx_data_req, - tx_slot_dec, tx_buffer_index, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); + slot_dec, buffer_index_rx, rx_slot_buffer->dl_tti_req, rx_slot_buffer->tx_data_req, + tx_slot_dec, buffer_index_tx, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); //TODO: Change later if required - - // if the subframe buffer sfn sf is set then we have atlease 1 message - // from the vnf. // todo : how to handle the messages we don't have, send dummies for // now @@ -1006,12 +996,15 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl //printf("tx_slot_buff_sfn - %d, tx_slot_buf_slot - %d, sfn_tx = %d, sllot_tx - %d \n",tx_slot_buffer->sfn,tx_slot_buffer->slot,sfn_tx,slot_tx); // if(tx_slot_buffer->slot == slot_tx && tx_slot_buffer->sfn == sfn_tx) // { - - if(tx_slot_buffer->tx_data_req != 0) + + //checking in the tx slot buffers to see if a p7 msg is present. todo: what if it's a mixed slot? + + if(tx_slot_buffer->tx_data_req != 0 && tx_slot_buffer->tx_data_req->SFN == sfn_tx && tx_slot_buffer->tx_data_req->Slot == slot_tx) { if(pnf_p7->_public.tx_data_req_fn) - { + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling tx_data_req_fn in SFN/slot %d.%d \n",sfn,slot); (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); } } @@ -1027,11 +1020,11 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl } } - - if(tx_slot_buffer->dl_tti_req != 0) + if(tx_slot_buffer->dl_tti_req != 0 && tx_slot_buffer->dl_tti_req->SFN == sfn_tx && tx_slot_buffer->dl_tti_req->Slot == slot_tx) { if(pnf_p7->_public.dl_tti_req_fn) { + LOG_D(PHY, "Process dl_tti SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->dl_tti_req); } } @@ -1047,10 +1040,11 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl } - if(tx_slot_buffer->ul_dci_req!= 0) + if(tx_slot_buffer->ul_dci_req!= 0 && tx_slot_buffer->ul_dci_req->SFN == sfn_tx && tx_slot_buffer->ul_dci_req->Slot == slot_tx) { if(pnf_p7->_public.ul_dci_req_fn) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling UL_dci_req_fn in SFN/slot %d.%d \n",sfn,slot); (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_dci_req); } } @@ -1064,27 +1058,14 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_dci_req); } } - if(tx_slot_buffer->ul_tti_req != 0) - { - if(pnf_p7->_public.ul_tti_req_fn) - { - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_tti_req); - } - } - else - { - // send dummy - if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) - { - pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn_tx; - pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot_tx; - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); - } - } + + //deallocate slot buffers after passing down the PDUs to PHY processing + if(tx_slot_buffer->dl_tti_req != 0) { deallocate_nfapi_dl_tti_request(tx_slot_buffer->dl_tti_req, pnf_p7); tx_slot_buffer->dl_tti_req = 0; + LOG_D(PHY,"SFN/slot %d.%d Buffer index : %d freed \n",sfn_tx,slot_tx,buffer_index_tx); } if(tx_slot_buffer->tx_data_req != 0) @@ -1098,72 +1079,51 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl deallocate_nfapi_ul_dci_request(tx_slot_buffer->ul_dci_req, pnf_p7); tx_slot_buffer->ul_dci_req = 0; } + + + //checking in the rx slot buffers to see if a p7 msg is present. + + if(rx_slot_buffer->ul_tti_req != 0 && rx_slot_buffer->ul_tti_req->SFN == sfn && rx_slot_buffer->ul_tti_req->Slot == slot) + { + if(pnf_p7->_public.ul_tti_req_fn) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling UL_tti_req_fn in SFN/slot %d.%d \n",sfn,slot); + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), rx_slot_buffer->ul_tti_req); + } + } else { - // If we ever need to "send" a dummy ul_config this won't work!!! - // send_dummy_subframe(pnf_p7, sfn_sf_tx); + // send dummy + if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) + { + pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; + pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); + } + } + if(rx_slot_buffer->ul_tti_req != 0) + { + deallocate_nfapi_ul_tti_request(rx_slot_buffer->ul_tti_req, pnf_p7); + rx_slot_buffer->ul_tti_req = 0; - // send_dummy_slot(pnf_p7, sfn_tx, slot_tx); } + //reset slot buffer - - if(slot_buffer->sfn == sfn && slot_buffer->slot == slot ) + if ( rx_slot_buffer->dl_tti_req == 0 && + rx_slot_buffer->tx_data_req == 0 && + rx_slot_buffer->ul_tti_req == 0) { - - if(slot_buffer->ul_tti_req != 0) - { - if(pnf_p7->_public.ul_tti_req_fn) - { - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), slot_buffer->ul_tti_req); - } - } - else - { - // send dummy - if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) - { - pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; - pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); - } - } - //if(subframe_buffer->dl_config_req != 0) - //deallocate_nfapi_dl_config_request(subframe_buffer->dl_config_req, pnf_p7); - //if(subframe_buffer->tx_req != 0) - //deallocate_nfapi_tx_request(subframe_buffer->tx_req, pnf_p7); - if(slot_buffer->ul_tti_req != 0) - { - deallocate_nfapi_ul_tti_request(slot_buffer->ul_tti_req, pnf_p7); - slot_buffer->ul_tti_req = 0; - - } - #if 0 - if(slot_buffer->lbt_dl_config_req != 0) - { - deallocate_nfapi_lbt_dl_config_request(slot_buffer->lbt_dl_config_req, pnf_p7); - slot_buffer->lbt_dl_config_req = 0; - } - #endif - } // sfn_slot match - - - if ( slot_buffer->dl_tti_req == 0 && - slot_buffer->tx_data_req == 0 && - slot_buffer->ul_tti_req == 0) - //slot_buffer->lbt_dl_config_req == 0 && - //slot_buffer->ue_release_req == 0) - { - memset(&(pnf_p7->slot_buffer[buffer_index]), 0, sizeof(nfapi_pnf_p7_slot_buffer_t)); - pnf_p7->slot_buffer[buffer_index].sfn = -1; - pnf_p7->slot_buffer[buffer_index].slot = -1; + memset(&(pnf_p7->slot_buffer[buffer_index_rx]), 0, sizeof(nfapi_pnf_p7_slot_buffer_t)); + pnf_p7->slot_buffer[buffer_index_rx].sfn = -1; + pnf_p7->slot_buffer[buffer_index_rx].slot = -1; } //printf("pnf_p7->_public.timing_info_mode_periodic:%d pnf_p7->timing_info_period_counter:%d pnf_p7->_public.timing_info_period:%d\n", pnf_p7->_public.timing_info_mode_periodic, pnf_p7->timing_info_period_counter, pnf_p7->_public.timing_info_period); //printf("pnf_p7->_public.timing_info_mode_aperiodic:%d pnf_p7->timing_info_aperiodic_send:%d\n", pnf_p7->_public.timing_info_mode_aperiodic, pnf_p7->timing_info_aperiodic_send); //printf("pnf_p7->timing_info_ms_counter:%d\n", pnf_p7->timing_info_ms_counter); - // send the periodic timing info if configured + //send the periodic timing info if configured if(pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) { pnf_nr_pack_and_send_timing_info(pnf_p7); @@ -1179,29 +1139,9 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl else { pnf_p7->timing_info_ms_counter++; - } + } //gokul } - else - { - //send_dummy_subframe(pnf_p7, sfn_sf_tx); - } - - - //printf("pnf_p7->tick:%d\n", pnf_p7->tick); - // if(pnf_p7->tick == 1000) // why? - // { - // // TODO: change stats to nr_stats - // NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF P7:%d] (ONTIME/LATE) DL:(%d/%d) UL:(%d/%d) HI:(%d/%d) TX:(%d/%d)\n", pnf_p7->_public.phy_id, - // pnf_p7->stats.dl_conf_ontime, pnf_p7->stats.dl_conf_late, - // pnf_p7->stats.ul_conf_ontime, pnf_p7->stats.ul_conf_late, - // pnf_p7->stats.hi_dci0_ontime, pnf_p7->stats.hi_dci0_late, - // pnf_p7->stats.tx_ontime, pnf_p7->stats.tx_late); - // pnf_p7->tick = 0; - // memset(&pnf_p7->stats, 0, sizeof(pnf_p7->stats)); - // } - // pnf_p7->tick++; - if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) { @@ -1654,34 +1594,18 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); return; } -#if 0 - if ( - 0 && - (NFAPI_SFNSF2DEC(req->sfn_sf) % 100 ==0 || - NFAPI_SFNSF2DEC(req->sfn_sf) % 105 ==0 - ) - ) - NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req sfn_sf:%d pdcch:%u dci:%u pdu:%u pdsch_rnti:%u pcfich:%u\n", - NFAPI_SFNSF2DEC(req->sfn_sf), - req->dl_config_request_body.number_pdcch_ofdm_symbols, - req->dl_config_request_body.number_dci, - req->dl_config_request_body.number_pdu, - req->dl_config_request_body.number_pdsch_rnti, - req->dl_config_request_body.transmission_power_pcfich - ); -#endif - if(is_nr_p7_request_in_window(req->SFN,req->Slot, "dl_tti_request", pnf_p7)) - { - uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + if(is_nr_p7_request_in_window(req->SFN,req->Slot, "dl_tti_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % 20; - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); - //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE DL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() POPULATE DL_TTI_REQ SFN/slot: %d.%d buffer_index:%d\n", __FUNCTION__, req->SFN, req->Slot, buffer_index); - // if there is already an dl_config_req make sure we free it. + // if there is already an dl_tti_req make sure we free it. if(pnf_p7->slot_buffer[buffer_index].dl_tti_req != 0) { NFAPI_TRACE(NFAPI_TRACE_NOTE, "%s() is_nr_p7_request_in_window()=TRUE buffer_index occupied - free it first sfn_slot:%d buffer_index:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(req->SFN,req->Slot), buffer_index); @@ -1691,7 +1615,7 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) deallocate_nfapi_dl_tti_request(pnf_p7->slot_buffer[buffer_index].dl_tti_req, pnf_p7); } - // saving dl_config_request in subframe buffer + // filling dl_tti_request in slot buffer pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; pnf_p7->slot_buffer[buffer_index].slot = req->Slot; pnf_p7->slot_buffer[buffer_index].dl_tti_req = req; @@ -1840,7 +1764,7 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) if(is_nr_p7_request_in_window(req->SFN,req->Slot, "ul_tti_request", pnf_p7)) { uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + uint8_t buffer_index = sfn_slot_dec % 20; struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); @@ -1855,6 +1779,8 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) deallocate_nfapi_ul_tti_request(pnf_p7->slot_buffer[buffer_index].ul_tti_req, pnf_p7); } + + //filling slot buffer pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; pnf_p7->slot_buffer[buffer_index].slot = req->Slot; @@ -1986,7 +1912,7 @@ void pnf_handle_ul_dci_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) if(is_nr_p7_request_in_window(req->SFN,req->Slot,"ul_dci_request", pnf_p7)) { uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + uint8_t buffer_index = sfn_slot_dec % 20; if(pnf_p7->slot_buffer[buffer_index].ul_dci_req!= 0) { @@ -2125,7 +2051,7 @@ void pnf_handle_tx_data_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 if(is_nr_p7_request_in_window(req->SFN, req->Slot,"tx_request", pnf_p7)) { uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + uint8_t buffer_index = sfn_slot_dec % 20; struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); @@ -2692,9 +2618,7 @@ void pnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: pnf_nr_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); break; - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - //printf("\nEntering pnf_handle_dl_tti_request sfn=%d,slot=%d \n",pnf_p7->sfn,pnf_p7->slot); pnf_handle_dl_tti_request(pRecvMsg, recvMsgLen, pnf_p7); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 11885d7c48..7f5d33466d 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -2011,7 +2011,9 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ +{ + uint8_t uplink_slots[6] = {7,8,9,17,18,19}; + uint8_t is_uplink_slot = 0; if (pRecvMsg == NULL || vnf_p7 == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_timing_info: NULL parameters\n"); @@ -2030,16 +2032,20 @@ void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) //int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf); int16_t vnf_pnf_sfnslot_delta = NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot) - NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta); - // Panos: Careful here!!! Modification of the original nfapi-code //if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1) //printf("VNF-PNF delta - %d", vnf_pnf_sfnslot_delta); - if (vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) + for (int i = 0; i < 6; i++){ + if (vnf_p7->p7_connections[0].slot == uplink_slots[i]) + is_uplink_slot = 1; + } + if ((vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) && is_uplink_slot == 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnslot_delta,NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot),NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot)) ; // Panos: Careful here!!! Modification of the original nfapi-code vnf_p7->p7_connections[0].sfn = ind.last_sfn; vnf_p7->p7_connections[0].slot = ind.last_slot; + //printf("VNF SFN/slot modified"); } } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index b84003ab6e..71a912057e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -157,10 +157,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) struct timespec pselect_start; struct timespec pselect_stop; - //struct timespec sf_end; - - long last_millisecond = -1; - // struct timespec sf_duration; //Change to slot_duration? // sf_duration.tv_sec = 0; @@ -200,263 +196,79 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) setup_time = curr_time.tv_sec - ref_time.tv_sec; clock_gettime(CLOCK_MONOTONIC, &pselect_start); - //long millisecond = pselect_start.tv_nsec / 1e6; - if((last_millisecond == -1) || (millisecond == last_millisecond) || (millisecond == (last_millisecond + 1) % 1000) ) + //NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec); + + if((pselect_start.tv_sec > slot_start.tv_sec) || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec); - - - //if((pselect_start.tv_sec > sf_start.tv_sec) || - // ((pselect_start.tv_sec == sf_start.tv_sec) && (pselect_start.tv_nsec > sf_start.tv_nsec))) - if((pselect_start.tv_sec > slot_start.tv_sec) || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) - { - // overran the end of the subframe we do not want to wait - pselect_timeout.tv_sec = 0; - pselect_timeout.tv_nsec = 0; - - //struct timespec overrun = timespec_sub(pselect_start, sf_start); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); - } - else - { - // still time before the end of the subframe wait - //pselect_timeout = timespec_sub(sf_start, pselect_start); - pselect_timeout = timespec_sub(slot_start, pselect_start); - } - -//original_pselect_timeout = pselect_timeout; - - // detemine how long to sleep in ns before the start of the next 1ms - //pselect_timeout.tv_nsec = 1e6 - (pselect_start.tv_nsec % 1000000); - - //uint8_t underrun_possible =0; - - // if we are not sleeping until the next milisecond due to the - // insycn minor adjment flag it so we don't consider it an error - //uint8_t underrun_possible =0; - /* - { - nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections; - if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0 && pselect_start.tv_nsec != 0) - { - NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] Subframe minor adjustment %d (%d->%d)\n", phy->insync_minor_adjustment, - pselect_timeout.tv_nsec, pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000)) - if(phy->insync_minor_adjustment > 0) - { - // todo check we don't go below 0 - if((phy->insync_minor_adjustment * 1000) > pselect_timeout.tv_nsec) - pselect_timeout.tv_nsec = 0; - else - pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000); - - - //underrun_possible = 1; - } - else if(phy->insync_minor_adjustment < 0) - { - // todo check we don't go below 0 - pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000); - - - //phy->insync_minor_adjustment = 0; - phy->insync_minor_adjustment_duration--; - } - } - */ - - if(setup_time > 10 && slot_scheduled == 0){ - - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; - - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); - //printf("Scheduler called at SFN/slot %d.%d. \n",vnf_frame,vnf_slot); - slot_scheduled = 1; - } - -//long wraps = pselect_timeout.tv_nsec % 1e9; - - // pselect_timeout.tv_sec = 100; // 0 - // pselect_timeout.tv_nsec = 0;//500000; // ns in a 0.5 ms - selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); - // selectRetval = pselect(120, &rfds, NULL, NULL, &pselect_timeout, NULL); - - clock_gettime(CLOCK_MONOTONIC, &pselect_stop); - - nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections; - -if (selectRetval==-1 && errno == 22) -{ -// NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n", -// pselect_timeout.tv_sec, pselect_timeout.tv_nsec, -// phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment, -// sf_duration.tv_sec, sf_duration.tv_nsec); - -NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n", - pselect_timeout.tv_sec, pselect_timeout.tv_nsec, - phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment, - slot_duration.tv_sec, slot_duration.tv_nsec); - -} - if(selectRetval == 0) - { - // calculate the start of the next slot - //sf_start = timespec_add(sf_start, sf_duration); - slot_start = timespec_add(slot_start, slot_duration); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec); - - if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0) - { - long insync_minor_adjustment_ns = (phy->insync_minor_adjustment * 1000); - - //sf_start.tv_nsec -= insync_minor_adjustment_ns; - slot_start.tv_nsec -= insync_minor_adjustment_ns; - -#if 1 -/* if (sf_start.tv_nsec > 1e9) //Change to 0.5e6? - { - sf_start.tv_sec++; - sf_start.tv_nsec-=1e9; - } - else if (sf_start.tv_nsec < 0) - { - sf_start.tv_sec--; - sf_start.tv_nsec+=1e9; - }*/ - if (slot_start.tv_nsec > 1e9) - { - slot_start.tv_sec++; - slot_start.tv_nsec-=1e9; - } - else if (slot_start.tv_nsec < 0) - { - slot_start.tv_sec--; - slot_start.tv_nsec+=1e9; - } -#else - //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] BEFORE adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d\n", phy->insync_minor_adjustment, sf_start.tv_nsec); - if(phy->insync_minor_adjustment > 0) - { - // decrease the subframe duration a little - if (sf_start.tv_nsec > insync_minor_adjustment_ns) - sf_start.tv_nsec -= insync_minor_adjustment_ns; - else - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] Adjustment would make it negative sf:%d.%ld adjust:%ld\n\n\n", sf_start.tv_sec, sf_start.tv_nsec, insync_minor_adjustment_ns); - sf_start.tv_sec--; - sf_start.tv_nsec += 1e9 - insync_minor_adjustment_ns; - } - } - else if(phy->insync_minor_adjustment < 0) - { - // todo check we don't go below 0 - // increase the subframe duration a little - sf_start.tv_nsec += insync_minor_adjustment_ns; - - if (sf_start.tv_nsec < 0) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] OVERFLOW %d.%ld\n\n\n\n", sf_start.tv_sec, sf_start.tv_nsec); - sf_start.tv_sec++; - sf_start.tv_nsec += 1e9; - } - } -#endif - - //phy->insync_minor_adjustment = 0; - phy->insync_minor_adjustment_duration--; - -// NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d duration:%u\n", -// phy->insync_minor_adjustment, sf_start.tv_nsec, phy->insync_minor_adjustment_duration); - // NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Slot minor adjustment %dus slot_start.tv_nsec:%d duration:%u\n", - // phy->insync_minor_adjustment, slot_start.tv_nsec, phy->insync_minor_adjustment_duration); - - if (phy->insync_minor_adjustment_duration==0) - { - phy->insync_minor_adjustment = 0; - } - } - /* - long pselect_stop_millisecond = pselect_stop.tv_nsec / 1e6; - if(millisecond == pselect_stop_millisecond) - { - // we have woke up in the same subframe - if(underrun_possible == 0) - NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect underrun %ld (%d.%d)\n", millisecond, pselect_stop.tv_sec, pselect_stop.tv_nsec); - } - else if(((millisecond + 1) % 1000) != pselect_stop_millisecond) - { - // we have overrun the subframe - NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect overrun %ld %ld\n", millisecond, pselect_stop_millisecond); - NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe underrun %ld\n", millisecond); - } - last_millisecond = millisecond; - */ - - //millisecond ++; - millisecond = millisecond + 1; - - } + // overran the end of the subframe we do not want to wait + pselect_timeout.tv_sec = 0; + pselect_timeout.tv_nsec = 0; + LOG_D(MAC, "Slot overrun detected \n"); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Slot overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); } else { - // we have overrun the subframe advance to go and collect $200 - - if((millisecond - last_millisecond) > 3) - NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe overrun %ld %ld (%ld)\n", millisecond, last_millisecond, millisecond - last_millisecond + 1); - - last_millisecond = ( last_millisecond + 1 ) % 1000; - selectRetval = 0; + // still time before the end of the subframe wait + pselect_timeout = timespec_sub(slot_start, pselect_start); } + if(setup_time > 10 && slot_scheduled == 0){ + + // Call the scheduler + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_frame; + gNB->UL_INFO.slot = vnf_slot; + + gNB->UL_INFO.module_id = gNB->Mod_id; + gNB->UL_INFO.CC_id = gNB->CC_id; + gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + slot_scheduled = 1; + } + + selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); + + clock_gettime(CLOCK_MONOTONIC, &pselect_stop); + nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; - uint8_t ul_p7_count = 0; + if(selectRetval == 0) { - //vnf_p7->sf_start_time_hr = vnf_get_current_time_hr(); - vnf_p7->slot_start_time_hr = vnf_get_current_time_hr(); -struct timespec current_time; - clock_gettime(CLOCK_MONOTONIC, ¤t_time); // pselect timed out - - // if(setup_time > 10){ - // // Call the scheduler - // struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - // pthread_mutex_lock(&gNB->UL_INFO_mutex); - // gNB->UL_INFO.frame = vnf_frame; - // gNB->UL_INFO.slot = vnf_slot; - // gNB->UL_INFO.module_id = gNB->Mod_id; - // gNB->UL_INFO.CC_id = gNB->CC_id; - // gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - // pthread_mutex_unlock(&gNB->UL_INFO_mutex); - // } + // calculate the start of the next slot + + slot_start = timespec_add(slot_start, slot_duration); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec); + if (slot_start.tv_nsec > 1e9) + { + slot_start.tv_sec++; + slot_start.tv_nsec-=1e9; + } + else if (slot_start.tv_nsec < 0) + { + slot_start.tv_sec--; + slot_start.tv_nsec+=1e9; + } + + vnf_p7->slot_start_time_hr = vnf_get_current_time_hr(); while(curr != 0) { if (curr->slot == 19) - { //curr->slot = 0; - if(curr->sfn == 1023) - curr->sfn=0; - else - curr->sfn++; - curr->slot=0; + { + curr->sfn = (curr->sfn + 1) % 1024; + curr->slot=0; } else { curr->slot++; } //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); - vnf_frame = curr->sfn; vnf_slot = curr->slot; - - struct timespec curr_time; - clock_gettime(CLOCK_MONOTONIC, &curr_time); + vnf_frame = curr->sfn; + vnf_slot = curr->slot; //vnf_nr_sync(vnf_p7, curr); @@ -466,6 +278,7 @@ struct timespec current_time; } send_mac_slot_indications(vnf_p7); slot_scheduled = 0; + } else if(selectRetval > 0) { @@ -484,7 +297,7 @@ struct timespec current_time; } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond); // should we exit now? if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration { @@ -492,10 +305,7 @@ struct timespec current_time; } } } - } - - NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n"); close(vnf_p7->socket); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c index 39900113b7..a82356f16a 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c @@ -780,11 +780,11 @@ int dlsch_encoding_SIC(PHY_VARS_UE *ue, for (r=0; rharq_processes[harq_pid]->C; r++) { #ifdef DEBUG_DLSCH_CODING - printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb); + // printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", + // r, + // G, + // Kr*3, + // mod_order,nb_rb); #endif start_meas(rm_stats); #ifdef DEBUG_DLSCH_CODING diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 7d9d55808a..a60a68de90 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -134,6 +134,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, /* advance last round's future UL_tti_req to be ahead of current frame/slot */ future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024; + LOG_D(MAC,"Future_ul_tti SFN = %d for slot %d \n", future_ul_tti_req->SFN, (slotP + num_slots - 1) % num_slots); /* future_ul_tti_req->Slot is fixed! */ future_ul_tti_req->n_pdus = 0; future_ul_tti_req->n_ulsch = 0; @@ -374,9 +375,10 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, if (NFAPI_MODE == NFAPI_MODE_VNF){ if(first_sched_entry == 1) { + printf("First sched entry at slot %d \n", slot); for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = frame + 1; + gNB->UL_tti_req_ahead[CC_id][i].SFN = (frame + 1) % 1024; else gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index fde53c3d0c..3b6655bd99 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -46,7 +46,6 @@ void nr_fill_nfapi_pucch(module_id_t mod_id, nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot]; - AssertFatal(future_ul_tti_req->SFN == pucch->frame && future_ul_tti_req->Slot == pucch->ul_slot, "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n", @@ -1140,10 +1139,6 @@ int nr_acknack_scheduling(int mod_id, __func__, pucch->csi_bits); /* if the currently allocated PUCCH of this UE is full, allocate it */ - // if (NFAPI_MODE == NFAPI_MODE_VNF){ - // pucch->sr_flag = 1; - // pucch->dai_c = 1; - // } if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in @@ -1174,7 +1169,7 @@ int nr_acknack_scheduling(int mod_id, /* if the UE's next PUCCH occasion is after the possible UL slots (within the * same frame) or wrapped around to the next frame, then we assume there is * no possible PUCCH allocation anymore */ - if(NFAPI_MODE == NFAPI_MONOLITHIC) + if ((pucch->frame == frame && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)) || (pucch->frame == frame + 1)) @@ -1186,10 +1181,10 @@ int nr_acknack_scheduling(int mod_id, get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); /* there is a HARQ. Check whether we can use it for this ACKNACK */ - // if(NFAPI_MODE == NFAPI_MODE_VNF) - // return 0; + if (pucch->dai_c > 0) { /* this UE already has a PUCCH occasion */ + LOG_I(MAC,"pucch->frame = %d,frame=%d \n",pucch->frame,frame); DevAssert(pucch->frame == frame); // Find the right timing_indicator value. diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index f90361f564..5a1cb970eb 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -88,7 +88,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->uci_ind.num_ucis>0) { - LOG_I(PHY,"PNF Sending UL_info->num_ucis:%d PDU_type: %d, SFN/SF:%d.%d \n", UL_info->uci_ind.num_ucis, UL_info->uci_ind.uci_list[0].pdu_type ,UL_info->frame, UL_info->slot); + LOG_D(PHY,"PNF Sending UL_info->num_ucis:%d PDU_type: %d, SFN/SF:%d.%d \n", UL_info->uci_ind.num_ucis, UL_info->uci_ind.uci_list[0].pdu_type ,UL_info->frame, UL_info->slot); oai_nfapi_nr_uci_indication(&UL_info->uci_ind); UL_info->uci_ind.num_ucis = 0; } @@ -99,7 +99,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) const sub_frame_t slot = UL_info->slot; int num_ucis = UL_info->uci_ind.num_ucis; nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; - //printf("handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); + LOG_I(MAC,"handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); for (int i = 0; i < num_ucis; i++) { switch (uci_list[i].pdu_type) { case NFAPI_NR_UCI_PUSCH_PDU_TYPE: @@ -120,6 +120,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) break; } } + LOG_D(MAC, "UCI handled \n"); } } From 6d051b422940c4352074b230d29670cff495a08c Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Thu, 29 Jul 2021 15:08:55 +0200 Subject: [PATCH 124/185] Changes in ASN extraction PERL script --- .../ASN1_files/extract_asn1_from_spce.pl | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/extract_asn1_from_spce.pl b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/extract_asn1_from_spce.pl index 81193afd1d..bdcdef5939 100755 --- a/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/extract_asn1_from_spce.pl +++ b/openair2/RRC/NR/MESSAGES/asn1c/ASN1_files/extract_asn1_from_spce.pl @@ -26,38 +26,52 @@ while () { syswrite OUTPUT_FILE,"END\n\n"; - while() { - if( m/NR-UE-Variables DEFINITIONS AUTOMATIC TAGS ::=/){ - - syswrite OUTPUT_FILE,"$_ \n"; - syswrite OUTPUT_FILE,"BEGIN\n\n"; + while() { + if( m/PC5-RRC-Definitions DEFINITIONS AUTOMATIC TAGS ::=/){ + syswrite OUTPUT_FILE,"$_ \n"; + syswrite OUTPUT_FILE,"BEGIN\n\n"; - # Get all the text delimited by -- ASN1START and -- ASN1STOP - extract_asn1(); + # Get all the text delimited by -- ASN1START and -- ASN1STOP + extract_asn1(); - syswrite OUTPUT_FILE,"END\n\n"; + syswrite OUTPUT_FILE,"END\n\n"; - while() { + while() { + if( m/NR-UE-Variables DEFINITIONS AUTOMATIC TAGS ::=/){ + syswrite OUTPUT_FILE,"$_ \n"; + syswrite OUTPUT_FILE,"BEGIN\n\n"; + + # Get all the text delimited by -- ASN1START and -- ASN1STOP + extract_asn1(); + syswrite OUTPUT_FILE,"END\n\n"; + while() { + if( m/NR-Sidelink-Preconf DEFINITIONS AUTOMATIC TAGS ::=/){ + syswrite OUTPUT_FILE,"$_ \n"; + syswrite OUTPUT_FILE,"BEGIN\n\n"; + + # Get all the text delimited by -- ASN1START and -- ASN1STOP + extract_asn1(); + + syswrite OUTPUT_FILE,"END\n\n"; + while() { if( m/NR-InterNodeDefinitions DEFINITIONS AUTOMATIC TAGS ::=/){ - - syswrite OUTPUT_FILE,"$_ \n"; - syswrite OUTPUT_FILE,"BEGIN\n\n"; + syswrite OUTPUT_FILE,"$_ \n"; + syswrite OUTPUT_FILE,"BEGIN\n\n"; - # Get all the text delimited by -- ASN1START and -- ASN1STOP - extract_asn1(); + # Get all the text delimited by -- ASN1START and -- ASN1STOP + extract_asn1(); - syswrite OUTPUT_FILE,"END\n\n"; - - } + syswrite OUTPUT_FILE,"END\n\n"; + } } - - } - } - + } + } + } + } + } + } close(OUTPUT_FILE); } - - } close(INPUT_FILE); From 8cc1d0a2dea83a3b7c2af09c112fe5babf2bf55a Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Aug 2021 11:21:07 +0200 Subject: [PATCH 125/185] initialization of pdcp only in nos1 --- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 024896b28d..b27837043f 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -60,9 +60,10 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { nr_rrc_mac_config_req_ue(0,0,0,NULL,NULL,NULL,rrc_inst->scell_group_config); AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); - pdcp_layer_init(); - nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); - + if (IS_SOFTMODEM_NOS1){ + pdcp_layer_init(); + nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); + } // Allocate memory for ul_config_request in the mac instance. This is now a pointer and will // point to a list of structures (one for each UL slot) to store PUSCH scheduling parameters // received from UL DCI. From 74c5816c72d5f975e02d48a660151e44df572278 Mon Sep 17 00:00:00 2001 From: Rahul Gottipati Date: Thu, 5 Aug 2021 17:30:12 +0530 Subject: [PATCH 126/185] VNF clock dependency removed --- executables/nr-gnb.c | 6 +- nfapi/oai_integration/nfapi_pnf.c | 62 +++++++------------ nfapi/oai_integration/nfapi_pnf.h | 2 +- nfapi/oai_integration/nfapi_vnf.c | 44 ++++++++++++- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 1 + nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 45 +++++++++++++- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 33 +++++----- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 12 ++++ nfapi/open-nFAPI/vnf/inc/vnf_p7.h | 1 - .../vnf/public_inc/nfapi_vnf_interface.h | 2 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 31 +++++++++- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 22 +++---- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 2 +- openair1/SCHED_NR/fapi_nr_l1.c | 2 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 5 -- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 3 - openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 2 +- 19 files changed, 186 insertions(+), 93 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index dbf5fb8fb2..de24bb9136 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -142,16 +142,16 @@ void rx_func(void *param) { int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - + LOG_I(PHY,"slot rx %d \n", slot_rx); start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* if (NFAPI_MODE == NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick - //LOG_D(PHY, "oai_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); + //LOG_D(PHY, "oai_nfapi_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx); start_meas(&nfapi_meas); - oai_slot_ind(frame_rx, slot_rx); + handle_nr_slot_ind(frame_rx, slot_rx); stop_meas(&nfapi_meas); /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index da8912e6a9..520a5dc578 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -2304,50 +2304,24 @@ void oai_subframe_ind(uint16_t sfn, uint16_t sf) { } } +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) { -long shift_ns,prev_ts_nsec,shift_us; -void oai_slot_ind(uint16_t sfn, uint16_t slot) { - - //slow down PNF - - LOG_D(PHY,"%s(sfn:%d, slot:%d)\n", __FUNCTION__, sfn, slot); - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - - // if (!(sfn == 0 && slot == 0) && ts.tv_nsec > prev_ts_nsec){ - // shift_ns = ts.tv_nsec - prev_ts_nsec; - // shift_us = shift_ns/1000; - // printf("previous: %d, current: %d, shift: %d", prev_ts_nsec, ts.tv_nsec, shift_us); - // if(500-shift_us > 0) - // usleep(500-shift_us); - // // usleep(50); - // } - prev_ts_nsec = ts.tv_nsec; - - -//NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s %d.%d (sfn:%u slot:%u) SFN/SLOT(TX):%u\n", __FUNCTION__, ts.tv_sec, ts.tv_nsec, sfn, slot, NFAPI_SFNSLOT2DEC(sfn, slot)); - //TODO FIXME - HACK - DJP - using a global to bodge it in - if (p7_config_g != NULL && sync_var==0) { - // DONE: changed for NR x x x x x x x x x x x x x x - - - - - - : x (Frame), - (Slot) (max_numer =2) - uint16_t sfn_slot_tx = sfn<<6 | slot; - // if ((sfn % 100 == 0) && slot==0) { // DOUBT: Why 100? - // struct timespec ts; - // clock_gettime(CLOCK_MONOTONIC, &ts); - // NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s %d.%d (sfn:%u slot:%u) SFN/SLOT(TX):%u\n", __FUNCTION__, ts.tv_sec, ts.tv_nsec, sfn, slot, NFAPI_SFNSLOT2DEC(sfn, slot)); - // } - - //TODO: send p7_config instead of p7_config_g + //send VNF slot indication, which is aligned with TX thread, so that it can call the scheduler + nfapi_nr_slot_indication_scf_t *ind; + ind = (nfapi_nr_slot_indication_scf_t *) malloc(sizeof(nfapi_nr_slot_indication_scf_t)); + uint8_t slot_ahead = 6; + uint32_t sfn_slot_tx = sfnslot_add_slot(sfn, slot, slot_ahead); + uint16_t sfn_tx = NFAPI_SFNSLOT2SFN(sfn_slot_tx); + uint8_t slot_tx = NFAPI_SFNSLOT2SLOT(sfn_slot_tx); + + ind->sfn = sfn_tx; + ind->slot = slot_tx; + oai_nfapi_nr_slot_indication(ind); + + //copy data from appropriate p7 slot buffers into channel structures for PHY processing int slot_ret = nfapi_pnf_p7_slot_ind(p7_config_g, p7_config_g->phy_id, sfn, slot); - // if (subframe_ret) { - if (slot_ret) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s(frame:%u slot:%u) SFN/SLOT(TX):%u - PROBLEM with pnf_p7_slot_ind()\n", __FUNCTION__, sfn, slot, sfn_slot_tx, NFAPI_SFNSLOT2DEC(sfn, slot)); - // printing anything causes error: probably because there isn't enough time to accomodate a print statement - } else { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "***NFAPI subframe handler finished *** \n"); - } - } else { - } + return; } int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) { @@ -2401,6 +2375,12 @@ int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) { //NR UPLINK INDICATION +int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { + ind->header.phy_id = 1; + ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION; + return nfapi_pnf_p7_nr_slot_ind(p7_config_g, ind); +} + int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION; diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 61d4847eba..463bd42692 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -27,5 +27,5 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); void oai_subframe_ind(uint16_t sfn, uint16_t sf); -void oai_slot_ind(uint16_t sfn, uint16_t slot); +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); #endif diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 1bc2f70d93..8c8a19e883 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -33,10 +33,10 @@ #include "nfapi_nr_interface_scf.h" #include "nfapi_vnf_interface.h" +#include "nfapi_vnf.h" #include "nfapi.h" #include "vendor_ext.h" -#include "nfapi_vnf.h" #include "PHY/defs_eNB.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" @@ -1014,8 +1014,47 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ return 1; } +// void add_slot(uint16_t *frameP, uint16_t *slotP, int offset) +// { +// uint16_t num_slots = 20; // set based on numerlogy (fixing for 1) + +// *frameP = (*frameP + ((*slotP + offset) / num_slots))%1024; + +// *slotP = ((*slotP + offset) % num_slots); +// } + +// uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset) +// { +// uint32_t new_sfnslot; +// // uint16_t sfn = NFAPI_SFNSLOT2SFN(sfnslot); +// // uint16_t slot = NFAPI_SFNSLOT2SLOT(sfnslot); + +// //printf("%s() sfn:%u sf:%u\n", __FUNCTION__, sfn, sf); +// add_slot(&sfn, &slot, offset); + +// new_sfnslot = sfn<<6|slot; + +// //printf("%s() sfn:%u sf:%u offset:%d sfnsf:%d(DEC:%d) new:%d(DEC:%d)\n", __FUNCTION__, sfn, sf, offset, sfnsf, NFAPI_SFNSF2DEC(sfnsf), new_sfnsf, NFAPI_SFNSF2DEC(new_sfnsf)); + +// return new_sfnslot; +// } + //NR phy indication +int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { + + uint8_t vnf_slot_ahead = 2; + uint32_t vnf_sfn_slot = sfnslot_add_slot(ind->sfn, ind->slot, vnf_slot_ahead); + uint16_t vnf_sfn = NFAPI_SFNSLOT2SFN(vnf_sfn_slot); + uint8_t vnf_slot = NFAPI_SFNSLOT2SLOT(vnf_sfn_slot); //offsetting the vnf from pnf by vnf_slot_head slots + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + pthread_mutex_lock(&gNB->UL_INFO_mutex); + gNB->UL_INFO.frame = vnf_sfn; + gNB->UL_INFO.slot = vnf_slot; + pthread_mutex_unlock(&gNB->UL_INFO_mutex); + LOG_D(MAC, "VNF SFN/Slot %d.%d \n", gNB->UL_INFO.frame, gNB->UL_INFO.slot); +} + int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; pthread_mutex_lock(&gNB->UL_INFO_mutex); @@ -1282,6 +1321,7 @@ void *vnf_nr_p7_thread_start(void *ptr) { p7_vnf->config->nb_harq_indication = &phy_nb_harq_indication; p7_vnf->config->nrach_indication = &phy_nrach_indication; p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication; + p7_vnf->config->nr_slot_indication = &phy_nr_slot_indication; p7_vnf->config->nr_rx_data_indication = &phy_nr_rx_data_indication; p7_vnf->config->nr_uci_indication = &phy_nr_uci_indication; p7_vnf->config->nr_rach_indication = &phy_nr_rach_indication; @@ -1739,7 +1779,7 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) //LOG_I(PHY, "sfn:%d,slot:%d\n",dl_config_req->SFN,dl_config_req->Slot); //printf("\nEntering oai_nfapi_nr_dl_config_req sfn:%d,slot:%d\n",dl_config_req->SFN,dl_config_req->Slot); nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; - dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; + dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! int retval = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req); diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index faa30582dc..9c3dd6fd8f 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -673,6 +673,7 @@ typedef struct { #define NFAPI_NR_SLOT_INDICATION_PERIOD_NUMEROLOGY_3 125 //us typedef struct { + nfapi_p7_message_header_t header; uint16_t sfn; //0->1023 uint16_t slot;//0->319 diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index e18aa7fda2..c25e6bc11c 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -3355,6 +3355,20 @@ static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_ //NR UPLINK indication function packing +//SLOT INDICATION + +static uint8_t pack_nr_slot_indication(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg; + + if (!(push16((uint16_t)pNfapiMsg->sfn , ppWritePackedMsg, end) && + push16((uint16_t)pNfapiMsg->slot , ppWritePackedMsg, end) + )) + return 0; + +return 1; +} + //RX DATA INDICATION static uint8_t pack_nr_rx_data_indication_body(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) @@ -3696,18 +3710,19 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe // look for the specific message uint8_t result = 0; switch (pMessageHeader->message_id) - { + { case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); - //printf("result of pack dl_tti_req is %d. \n",result); break; case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -3720,6 +3735,9 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); break; + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + result = pack_nr_slot_indication(pMessageHeader, &pWritePackedMessage, end, config); + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: result = pack_nr_rx_data_indication(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -6350,6 +6368,21 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * //UNPACK NR UPLINK INDICATION FUNCTIONS +//SLOT INDICATION + +static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg; + + printf("\n"); + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && + pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) + )) + return 0; + +return 1; +} + //RX DATA INDICATION static uint8_t unpack_nr_rx_data_indication_body(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) @@ -8707,6 +8740,14 @@ int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void * else return -1; break; + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION, unpackedBufLen)){ + nfapi_nr_slot_indication_scf_t* msg = (nfapi_nr_slot_indication_scf_t*) pMessageHeader; + result = unpack_nr_slot_indication(&pReadPackedMessage, end, msg, config); + } + else + return -1; + break; case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION, unpackedBufLen)){ diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 0b75d3c7ec..c04285c62e 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -940,11 +940,11 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. - pnf_p7->sfn = sfn_tx; + pnf_p7->sfn = sfn_tx; //gokul pnf_p7->slot = slot_tx; - uint32_t slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); - uint8_t buffer_index_rx = slot_dec % 20; + uint32_t rx_slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); + uint8_t buffer_index_rx = rx_slot_dec % 20; uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(sfn_tx,slot_tx); uint8_t buffer_index_tx = tx_slot_dec % 20; @@ -978,14 +978,14 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); - if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d slot_buffer->sfn_sf:%d tx_slot_buffer->sfn_slot:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] " - "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", - __FUNCTION__, - pnf_p7->slot_shift, - NFAPI_SFNSLOT2DEC(rx_slot_buffer->sfn, rx_slot_buffer->slot), - NFAPI_SFNSLOT2DEC(tx_slot_buffer->sfn, tx_slot_buffer->slot), - slot_dec, buffer_index_rx, rx_slot_buffer->dl_tti_req, rx_slot_buffer->tx_data_req, - tx_slot_dec, buffer_index_tx, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); + // if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d slot_buffer->sfn_sf:%d tx_slot_buffer->sfn_slot:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] " + // "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", + // __FUNCTION__, + // pnf_p7->slot_shift, + // NFAPI_SFNSLOT2DEC(rx_slot_buffer->sfn, rx_slot_buffer->slot), + // NFAPI_SFNSLOT2DEC(tx_slot_buffer->sfn, tx_slot_buffer->slot), + // slot_dec, buffer_index_rx, rx_slot_buffer->dl_tti_req, rx_slot_buffer->tx_data_req, + // tx_slot_dec, buffer_index_tx, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); //TODO: Change later if required // todo : how to handle the messages we don't have, send dummies for @@ -1004,7 +1004,8 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl if(pnf_p7->_public.tx_data_req_fn) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling tx_data_req_fn in SFN/slot %d.%d \n",sfn,slot); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling tx_data_req_fn in SFN/slot %d.%d \n",sfn,slot); + LOG_D(PHY, "Process tx_data SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); } } @@ -1045,6 +1046,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl if(pnf_p7->_public.ul_dci_req_fn) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "Calling UL_dci_req_fn in SFN/slot %d.%d \n",sfn,slot); + LOG_D(PHY, "Process ul_dci SFN/slot %d.%d buffer index: %d \n",sfn_tx,slot_tx,buffer_index_tx); (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_dci_req); } } @@ -1098,6 +1100,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl { pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; + LOG_D(PHY, "Process ul_tti SFN/slot %d.%d buffer index: %d \n",sfn,slot,buffer_index_rx); (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); } } @@ -1603,7 +1606,7 @@ void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() POPULATE DL_TTI_REQ SFN/slot: %d.%d buffer_index:%d\n", __FUNCTION__, req->SFN, req->Slot, buffer_index); + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE DL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); // if there is already an dl_tti_req make sure we free it. if(pnf_p7->slot_buffer[buffer_index].dl_tti_req != 0) @@ -1764,12 +1767,12 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) if(is_nr_p7_request_in_window(req->SFN,req->Slot, "ul_tti_request", pnf_p7)) { uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); - uint8_t buffer_index = sfn_slot_dec % 20; + uint8_t buffer_index = (sfn_slot_dec % 20); struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) { diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 88aa1391cb..a5cd9bcd16 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -258,6 +258,18 @@ int nfapi_pnf_ue_release_resp(nfapi_pnf_p7_config_t* config, nfapi_ue_release_re //NR UPLINK INDICATION +int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_nr_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_nr_rx_data_indication_t)); +} + int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind) { if(config == NULL || ind == NULL) diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index ad1c5e7944..4fcc99f79b 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -25,7 +25,6 @@ #define TIME2TIMEHR(_time) (((uint32_t)(_time.tv_sec) & 0xFFF) << 20 | ((uint32_t)(_time.tv_usec) & 0xFFFFF)) - typedef struct { uint8_t* buffer; uint16_t length; diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index 14c53b870b..31328393c9 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -854,7 +854,7 @@ typedef struct nfapi_vnf_p7_config int (*nrach_indication)(struct nfapi_vnf_p7_config* config, nfapi_nrach_indication_t* ind); //The NR indication functions below copy uplink information received at the VNF into the UL info struct - + int (*nr_slot_indication)(nfapi_nr_slot_indication_scf_t* ind); int (*nr_crc_indication)(nfapi_nr_crc_indication_t* ind); int (*nr_rx_data_indication)(nfapi_nr_rx_data_indication_t* ind); int (*nr_uci_indication)(nfapi_nr_uci_indication_t* ind); diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 7f5d33466d..4b68f016a8 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -23,7 +23,6 @@ #include #include #include - #include "vnf_p7.h" #define SYNC_CYCLE_COUNT 2 @@ -1455,7 +1454,31 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } //NR HANDLES FOR UPLINK MESSAGES +void vnf_handle_nr_slot_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + // ensure it's valid + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_slot_indication_scf_t ind; + + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(ind), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Failed to unpack message\n", __FUNCTION__); + } + else + { + if(vnf_p7->_public.nr_slot_indication) + { + (vnf_p7->_public.nr_slot_indication)(&ind); //gokul + } + } + } +} void vnf_handle_nr_rx_data_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { // ensure it's valid @@ -2179,7 +2202,11 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 case NFAPI_TIMING_INFO: vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); break; - + + case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: + vnf_handle_nr_slot_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: vnf_handle_nr_rx_data_indication(pRecvMsg, recvMsgLen, vnf_p7); break; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 71a912057e..5c0ff7b068 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -25,6 +25,7 @@ #include #include "vnf_p7.h" +#include "nfapi_vnf.h" #include "common/ran_context.h" @@ -96,8 +97,10 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // monitor the p7 endpoints and the timing loop and // send indications to mac int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) -{ - uint16_t vnf_frame; uint8_t vnf_slot; uint16_t slot_scheduled; +{ + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + uint8_t temp_slot; + uint16_t vnf_frame; uint8_t vnf_slot; if(config == 0) return -1; @@ -150,8 +153,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) //struct timespec original_pselect_timeout; struct timespec pselect_timeout; - pselect_timeout.tv_sec = 0; - pselect_timeout.tv_nsec = 500000; // ns in a 0.5 ms + pselect_timeout.tv_sec = 100; + pselect_timeout.tv_nsec = 0; // ns in a 0.5 ms //pselect_timeout.tv_nsec = 500000; struct timespec pselect_start; @@ -213,19 +216,15 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) pselect_timeout = timespec_sub(slot_start, pselect_start); } - if(setup_time > 10 && slot_scheduled == 0){ + if(setup_time > 10 && temp_slot != gNB->UL_INFO.slot){ - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + //Call the scheduler pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; - gNB->UL_INFO.module_id = gNB->Mod_id; gNB->UL_INFO.CC_id = gNB->CC_id; gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); - slot_scheduled = 1; + temp_slot = gNB->UL_INFO.slot; } selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); @@ -277,7 +276,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) curr = curr->next; } send_mac_slot_indications(vnf_p7); - slot_scheduled = 0; } else if(selectRetval > 0) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 2ae2549df3..e01adc1bf2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -292,7 +292,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); - LOG_D(NR_PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,mod_order); + LOG_I(NR_PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,mod_order); if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 42441e9f53..23e18f5787 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -268,7 +268,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ //printf("Inside NR schedule response SFN/slot %d.%d. \n",frame,slot); if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) { - //printf("SFN/slot %d.%d Sending ul tti req \n",frame,slot); + LOG_I(MAC,"SFN/slot %d.%d Sending ul tti req \n",frame,slot); oai_nfapi_ul_tti_req(UL_tti_req); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 9f40821d04..c1dd64af5d 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -164,7 +164,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id); if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) { - LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", + LOG_I(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", gNB->Mod_id, frame, slot, gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci, gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index b678988be1..5e474f1bd2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -406,7 +406,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, { printf("First sched entry at slot %d \n", slot); for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = (frame + 1) % 1024; else gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index c77bd93203..9da818c2ab 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -835,8 +835,6 @@ void nr_schedule_ue_spec(module_id_t module_id, int8_t current_harq_pid = sched_pdsch->dl_harq_pid; if (current_harq_pid < 0) { /* PP has not selected a specific HARQ Process, get a new one */ - // if (NFAPI_MODE == NFAPI_MODE_VNF) - // sched_ctrl->available_dl_harq.head = 0; current_harq_pid = sched_ctrl->available_dl_harq.head; AssertFatal(current_harq_pid >= 0, "no free HARQ process available for UE %d\n", @@ -853,9 +851,6 @@ void nr_schedule_ue_spec(module_id_t module_id, remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; - // if (NFAPI_MODE == NFAPI_MODE_VNF) { - // harq->is_waiting = false; - // } DevAssert(!harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[sched_pdsch->pucch_allocation]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 1eb7fa7f7d..139b22788d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -502,9 +502,6 @@ void nr_csi_meas_reporting(int Mod_idP, // find free PUCCH that is in order with possibly existing PUCCH // schedulings (other CSI, SR) NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1]; - // if(NFAPI_MODE == NFAPI_MODE_VNF){ - // curr_pucch->csi_bits = 0; curr_pucch->sr_flag = 0; curr_pucch->dai_c = 0; - // } AssertFatal(curr_pucch->csi_bits == 0 && !curr_pucch->sr_flag && curr_pucch->dai_c == 0, diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 5a1cb970eb..26978ebc30 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -99,7 +99,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) const sub_frame_t slot = UL_info->slot; int num_ucis = UL_info->uci_ind.num_ucis; nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; - LOG_I(MAC,"handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); + LOG_D(MAC,"handling UCI SFN/slot: %d.%d, num_ucis: %d \n", frame,slot, num_ucis); for (int i = 0; i < num_ucis; i++) { switch (uci_list[i].pdu_type) { case NFAPI_NR_UCI_PUSCH_PDU_TYPE: From 557b5445d385f5eef6d14e71d08173d0efdfaa91 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Sun, 8 Aug 2021 12:23:15 +0530 Subject: [PATCH 127/185] PNF config file pusch_proc_threads update --- targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf index 5cfd4dc768..51079cf604 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf @@ -28,6 +28,7 @@ L1s = ( remote_n_portc = 50001; // vnf p5 port local_n_portd = 50010; // pnf p7 port remote_n_portd = 50011; // vnf p7 port + pusch_proc_threads = 8; } ); From 387223eea680fbb3b396ba72dc4dc60a0645249e Mon Sep 17 00:00:00 2001 From: Rodolphe BERTOLINI Date: Mon, 9 Aug 2021 09:59:38 +0200 Subject: [PATCH 128/185] removed duplicate structure, changed 'x' to 'r' and 'y' to 'i' --- openair1/PHY/TOOLS/signal_energy.c | 4 +- openair1/PHY/TOOLS/tools_defs.h | 7 +- openair1/SIMULATION/TOOLS/multipath_channel.c | 2 +- openair1/SIMULATION/TOOLS/random_channel.c | 346 +++++++++--------- openair1/SIMULATION/TOOLS/sim.h | 8 +- targets/ARCH/rfsimulator/apply_channelmod.c | 12 +- 6 files changed, 187 insertions(+), 192 deletions(-) diff --git a/openair1/PHY/TOOLS/signal_energy.c b/openair1/PHY/TOOLS/signal_energy.c index f3dea58374..96ee211285 100644 --- a/openair1/PHY/TOOLS/signal_energy.c +++ b/openair1/PHY/TOOLS/signal_energy.c @@ -264,7 +264,7 @@ double signal_energy_fp(double *s_re[2],double *s_im[2],uint32_t nb_antennas,uin return(V/length/nb_antennas); } -double signal_energy_fp2(struct complex *s,uint32_t length) +double signal_energy_fp2(struct complexd *s,uint32_t length) { int32_t i; @@ -273,7 +273,7 @@ double signal_energy_fp2(struct complex *s,uint32_t length) for (i=0; i %f\n",s[i].x,s[i].y,V); // V= V + (s[i].y*s[i].x) + (s[i].y*s[i].x); - V= V + (s[i].x*s[i].x) + (s[i].y*s[i].y); + V= V + (s[i].r*s[i].r) + (s[i].i*s[i].i); } return(V/length); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 4c68c15cb6..966e93440e 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -39,11 +39,6 @@ extern "C" { #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) -struct complex { - double x; - double y; -}; - struct complexd { double r; double i; @@ -468,7 +463,7 @@ double signal_energy_fp(double *s_re[2], double *s_im[2], uint32_t nb_antennas, /*!\fn double signal_energy_fp2(struct complex *, uint32_t); \brief Computes the signal energy per subcarrier */ -double signal_energy_fp2(struct complex *s, uint32_t length); +double signal_energy_fp2(struct complexd *s, uint32_t length); int32_t iSqrt(int32_t value); diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index 3608eb7da2..cab812b054 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -156,7 +156,7 @@ void multipath_channel(channel_desc_t *desc, { int i,ii,j,l; - struct complex rx_tmp,tx; + struct complexd rx_tmp,tx; double path_loss = pow(10,desc->path_loss_dB/20); int dd; diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index d2339954bd..26fe0b1120 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -72,7 +72,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, uint8_t channel_length, double *amps, double *delays, - struct complex **R_sqrt, + struct complexd **R_sqrt, double Td, double sampling_rate, double channel_bandwidth, @@ -116,44 +116,44 @@ void fill_channel_desc(channel_desc_t *chan_desc, chan_desc->first_run = 1; chan_desc->ip = 0.0; chan_desc->max_Doppler = max_Doppler; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(nb_taps*sizeof(struct complexd *)); LOG_D(OCM,"[CHANNEL] Filling ch \n"); for (i = 0; ich[i] = (struct complex *) malloc(channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); // allocate for up to 100 RBs, 12 samples per RB + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); // allocate for up to 100 RBs, 12 samples per RB LOG_D(OCM,"[CHANNEL] Filling a (nb_taps %d)\n",nb_taps); for (i = 0; ia[i],nb_tx*nb_rx * sizeof(struct complex)); - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + LOG_D(OCM,"tap %d (%p,%zu)\n",i,&chan_desc->a[i],nb_tx*nb_rx * sizeof(struct complexd)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); } LOG_D(OCM,"[CHANNEL] Doing R_sqrt ...\n"); if (R_sqrt == NULL) { - chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); + chan_desc->R_sqrt = (struct complexd **) calloc(nb_taps,sizeof(struct complexd *)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_NTAPS ; for (i = 0; iR_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } } } else { - chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); + chan_desc->R_sqrt = (struct complexd **) calloc(nb_taps,sizeof(struct complexd *)); for (i = 0; iR_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); - //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; + //chan_desc->R_sqrt[i] = (struct complexd*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complexd)); + //chan_desc->R_sqrt = (struct complexd*)&R_sqrt[i][0]; /* all chan_desc share the same R_sqrt, coming from caller */ chan_desc->R_sqrt[i] = R_sqrt[0]; } @@ -161,7 +161,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, for (i = 0; iR_sqrt[i][j].x,chan_desc->R_sqrt[i][j].y); + LOG_D(OCM,"Rsqrt[%d][%d] %f %f\n",i,j,chan_desc->R_sqrt[i][j].r,chan_desc->R_sqrt[i][j].i); } } @@ -421,84 +421,84 @@ double ts_shift_delays[] = {0, 1/7.68}; double ts_shift_amps[] = {0, 1}; //correlation matrix for a 2x2 channel with full Tx correlation -struct complex R_sqrt_22_corr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, +struct complexd R_sqrt_22_corr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.70711,0} }; -struct complex *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap}; +struct complexd *R_sqrt_22_corr[1] = {R_sqrt_22_corr_tap}; //correlation matrix for a fully correlated 2x1 channel (h1==h2) -struct complex R_sqrt_21_corr_tap[4] = {{0.70711,0}, {0.70711,0}, {0.70711,0}, {0.70711,0}}; -struct complex *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap}; +struct complexd R_sqrt_21_corr_tap[4] = {{0.70711,0}, {0.70711,0}, {0.70711,0}, {0.70711,0}}; +struct complexd *R_sqrt_21_corr[1] = {R_sqrt_21_corr_tap}; //correlation matrix for a 2x2 channel with full Tx anti-correlation -struct complex R_sqrt_22_anticorr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, +struct complexd R_sqrt_22_anticorr_tap[16] = {{0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {-0.70711,0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0}, {0.0, 0.0}, {0.0, 0.0}, {-0.70711,0}, {0.0, 0.0}, {0.70711,0} }; -struct complex *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap}; +struct complexd *R_sqrt_22_anticorr[1] = {R_sqrt_22_anticorr_tap}; //correlation matrix for a fully anti-correlated 2x1 channel (h1==-h2) -struct complex R_sqrt_21_anticorr_tap[4] = {{0.70711,0}, {-0.70711,0}, {-0.70711,0}, {0.70711,0}}; -struct complex *R_sqrt_21_anticorr[1] = {R_sqrt_21_anticorr_tap}; +struct complexd R_sqrt_21_anticorr_tap[4] = {{0.70711,0}, {-0.70711,0}, {-0.70711,0}, {0.70711,0}}; +struct complexd *R_sqrt_21_anticorr[1] = {R_sqrt_21_anticorr_tap}; -struct complex **R_sqrt_ptr2; +struct complexd **R_sqrt_ptr2; // full correlation matrix in vectorized form for 2x2 channel, where h1 is perfectly orthogonal to h2 -struct complex R_sqrt_22_orthogonal_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, +struct complexd R_sqrt_22_orthogonal_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0} }; -struct complex *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; +struct complexd *R_sqrt_22_orthogonal[1] = {R_sqrt_22_orthogonal_tap}; // full correlation matrix for TM4 to make orthogonal effective channel -struct complex R_sqrt_22_orth_eff_ch_TM4_prec_real_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, +struct complexd R_sqrt_22_orth_eff_ch_TM4_prec_real_tap[16] = {{0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {-0.70711,0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.70711,0.0} }; -struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_real_tap}; +struct complexd *R_sqrt_22_orth_eff_ch_TM4_prec_real[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_real_tap}; -struct complex R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0}, +struct complexd R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap[16] = {{0.70711,0.0}, {0.0,0.0}, {0.0, -0.70711}, {0.0,0.0}, {0.0, 0.0}, {0.70711,0.0}, {0.0, 0.0}, {0.0,0.70711}, {0.0,-0.70711}, {0.0, 0.0}, {-0.70711,0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0,0.70711}, {0.0, 0.0}, {-0.70711,0.0} }; -struct complex *R_sqrt_22_orth_eff_ch_TM4_prec_imag[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap}; +struct complexd *R_sqrt_22_orth_eff_ch_TM4_prec_imag[1] = {R_sqrt_22_orth_eff_ch_TM4_prec_imag_tap}; //Correlation matrix for EPA channel -struct complex R_sqrt_22_EPA_low_tap[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, +struct complexd R_sqrt_22_EPA_low_tap[16] = {{1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {1.0,0.0} }; -struct complex *R_sqrt_22_EPA_low[1] = {R_sqrt_22_EPA_low_tap}; +struct complexd *R_sqrt_22_EPA_low[1] = {R_sqrt_22_EPA_low_tap}; -struct complex R_sqrt_22_EPA_high_tap[16] = { +struct complexd R_sqrt_22_EPA_high_tap[16] = { {0.7179,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.7179,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.7179,0.0}, {0.4500,0.0}, {0.2821,0.0}, {0.4500,0.0}, {0.4500,0.0}, {0.7179,0.0} }; -struct complex *R_sqrt_22_EPA_high[1] = {R_sqrt_22_EPA_high_tap}; +struct complexd *R_sqrt_22_EPA_high[1] = {R_sqrt_22_EPA_high_tap}; -struct complex R_sqrt_22_EPA_medium_tap[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, +struct complexd R_sqrt_22_EPA_medium_tap[16] = {{0.8375,0.0}, {0.5249,0.0}, {0.1286,0.0}, {0.0806,0.0}, {0.5249,0.0}, {0.8375,0.0}, {0.0806,0.0}, {0.1286,0.0}, {0.1286,0.0}, {0.0806,0.0}, {0.8375,0.0}, {0.5249,0.0}, {0.0806,0.0}, {0.1286,0.0}, {0.5249,0.0}, {0.8375,0.0} }; -struct complex *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap}; +struct complexd *R_sqrt_22_EPA_medium[1] = {R_sqrt_22_EPA_medium_tap}; @@ -535,37 +535,37 @@ void tdlModel(int tdl_paths, double *tdl_delays, double *tdl_amps_dB, double DS chan_desc->delays = tdl_delays; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (int i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (int i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (int i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); if (nb_tx==2 && nb_rx==2) { for (int i = 0; i<(tdl_pathsby3); i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else if (nb_tx==2 && nb_rx==1) { for (int i = 0; i<(tdl_pathsby3); i++) - chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R21_sqrt[i][0]; } else if (nb_tx==1 && nb_rx==2) { for (int i = 0; i<(tdl_pathsby3); i++) - chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R12_sqrt[i][0]; } else { for (int i = 0; i<(tdl_pathsby3); i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (int j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); @@ -648,39 +648,39 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); if (nb_tx==2 && nb_rx==2) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else if (nb_tx==2 && nb_rx==1) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R21_sqrt[i][0]; } else if (nb_tx==1 && nb_rx==2) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R12_sqrt[i][0]; } else { chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); @@ -710,39 +710,39 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 0.1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); if (nb_tx==2 && nb_rx==2) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else if (nb_tx==2 && nb_rx==1) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R21_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R21_sqrt[i][0]; } else if (nb_tx==1 && nb_rx==2) { for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R12_sqrt[i][0]; } else { chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix not implemented for nb_tx==%d and nb_rx==%d, using identity\n", nb_tx, nb_rx); @@ -807,34 +807,34 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); @@ -863,21 +863,21 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd **)); for (i = 0; inb_taps; i++) chan_desc->R_sqrt[i] = R_sqrt_22_EPA_low[0]; @@ -886,9 +886,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, } /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + chan_desc->R_sqrt = (struct complexd**) malloc(6*sizeof(struct complexd**)); for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -918,21 +918,21 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd **)); for (i = 0; inb_taps; i++) chan_desc->R_sqrt[i] = R_sqrt_22_EPA_high[0]; @@ -941,9 +941,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, } /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + chan_desc->R_sqrt = (struct complexd**) malloc(6*sizeof(struct complexd**)); for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -973,21 +973,21 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd **)); for (i = 0; inb_taps; i++) chan_desc->R_sqrt[i] = R_sqrt_22_EPA_medium[0]; @@ -996,9 +996,9 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, } /*else { - chan_desc->R_sqrt = (struct complex**) malloc(6*sizeof(struct complex**)); + chan_desc->R_sqrt = (struct complexd**) malloc(6*sizeof(struct complexd**)); for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd*) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -1028,34 +1028,34 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); @@ -1084,34 +1084,34 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); if (nb_tx==2 && nb_rx==2) { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); for (i = 0; i<6; i++) - chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; + chan_desc->R_sqrt[i] = (struct complexd *) &R22_sqrt[i][0]; } else { - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd **)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); @@ -1140,28 +1140,28 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->ricean_factor = 1; chan_desc->aoa = 0; chan_desc->random_aoa = 0; - chan_desc->ch = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->chF = (struct complex **) malloc(nb_tx*nb_rx*sizeof(struct complex *)); - chan_desc->a = (struct complex **) malloc(chan_desc->nb_taps*sizeof(struct complex *)); + chan_desc->ch = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->chF = (struct complexd **) malloc(nb_tx*nb_rx*sizeof(struct complexd *)); + chan_desc->a = (struct complexd **) malloc(chan_desc->nb_taps*sizeof(struct complexd *)); for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); + chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd)); for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); + chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd)); for (i = 0; inb_taps; i++) - chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd)); - chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex *)); + chan_desc->R_sqrt = (struct complexd **) malloc(6*sizeof(struct complexd *)); chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6; for (i = 0; i<6; i++) { - chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); + chan_desc->R_sqrt[i] = (struct complexd *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complexd)); for (j = 0; jR_sqrt[i][j].x = 1.0; - chan_desc->R_sqrt[i][j].y = 0.0; + chan_desc->R_sqrt[i][j].r = 1.0; + chan_desc->R_sqrt[i][j].i = 0.0; } LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); @@ -1729,8 +1729,8 @@ void set_channeldesc_name(channel_desc_t *cdesc,char *modelname) { int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { double s; int i,k,l,aarx,aatx; - struct complex anew[NB_ANTENNAS_TX*NB_ANTENNAS_RX],acorr[NB_ANTENNAS_TX*NB_ANTENNAS_RX]; - struct complex phase, alpha, beta; + struct complexd anew[NB_ANTENNAS_TX*NB_ANTENNAS_RX],acorr[NB_ANTENNAS_TX*NB_ANTENNAS_RX]; + struct complexd phase, alpha, beta; AssertFatal(desc->nb_tx<=NB_ANTENNAS_TX && desc->nb_rx <= NB_ANTENNAS_RX, "random_channel.c: Error: temporary buffer for channel not big enough (%d,%d)\n",desc->nb_tx,desc->nb_rx); start_meas(&desc->random_channel); @@ -1738,8 +1738,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { for (i=0; i<(int)desc->nb_taps; i++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - anew[aarx+(aatx*desc->nb_rx)].x = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); - anew[aarx+(aatx*desc->nb_rx)].y = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); + anew[aarx+(aatx*desc->nb_rx)].r = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); + anew[aarx+(aatx*desc->nb_rx)].i = sqrt(desc->ricean_factor*desc->amps[i]/2) * gaussdouble(0.0,1.0); if ((i==0) && (desc->ricean_factor != 1.0)) { if (desc->random_aoa==1) { @@ -1749,10 +1749,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { // this assumes that both RX and TX have linear antenna arrays with lambda/2 antenna spacing. // Furhter it is assumed that the arrays are parallel to each other and that they are far enough apart so // that we can safely assume plane wave propagation. - phase.x = cos(M_PI*((aarx-aatx)*sin(desc->aoa))); - phase.y = sin(M_PI*((aarx-aatx)*sin(desc->aoa))); - anew[aarx+(aatx*desc->nb_rx)].x += phase.x * sqrt(1.0-desc->ricean_factor); - anew[aarx+(aatx*desc->nb_rx)].y += phase.y * sqrt(1.0-desc->ricean_factor); + phase.r = cos(M_PI*((aarx-aatx)*sin(desc->aoa))); + phase.i = sin(M_PI*((aarx-aatx)*sin(desc->aoa))); + anew[aarx+(aatx*desc->nb_rx)].r += phase.r * sqrt(1.0-desc->ricean_factor); + anew[aarx+(aatx*desc->nb_rx)].i += phase.i * sqrt(1.0-desc->ricean_factor); } #ifdef DEBUG_CH @@ -1773,10 +1773,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { */ //apply correlation matrix //compute acorr = R_sqrt[i] * anew - alpha.x = 1.0; - alpha.y = 0.0; - beta.x = 0.0; - beta.y = 0.0; + alpha.r = 1.0; + alpha.i = 0.0; + beta.r = 0.0; + beta.i = 0.0; cblas_zgemv(CblasRowMajor, CblasNoTrans, desc->nb_tx*desc->nb_rx, desc->nb_tx*desc->nb_rx, (void *) &alpha, (void *) desc->R_sqrt[i/3], desc->nb_rx*desc->nb_tx, (void *) anew, 1, (void *) &beta, (void *) acorr, 1); @@ -1797,10 +1797,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { // a = alpha*acorr+beta*a // a = beta*a // a = a+alpha*acorr - alpha.x = sqrt(1-desc->forgetting_factor); - alpha.y = 0; - beta.x = sqrt(desc->forgetting_factor); - beta.y = 0; + alpha.r = sqrt(1-desc->forgetting_factor); + alpha.i = 0; + beta.r = sqrt(desc->forgetting_factor); + beta.i = 0; cblas_zscal(desc->nb_tx*desc->nb_rx, (void *) &beta, (void *) desc->a[i], 1); cblas_zaxpy(desc->nb_tx*desc->nb_rx, (void *) &alpha, (void *) acorr, 1, (void *) desc->a[i], 1); // desc->a[i][aarx+(aatx*desc->nb_rx)].x = (sqrt(desc->forgetting_factor)*desc->a[i][aarx+(aatx*desc->nb_rx)].x) + sqrt(1-desc->forgetting_factor)*anew.x; @@ -1820,7 +1820,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { stop_meas(&desc->random_channel); - //memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complex)); + //memset((void *)desc->ch[aarx+(aatx*desc->nb_rx)],0,(int)(desc->channel_length)*sizeof(struct complexd)); if (abstraction_flag==0) { start_meas(&desc->interp_time); @@ -1828,12 +1828,12 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { if (desc->channel_length == 1) { - desc->ch[aarx+(aatx*desc->nb_rx)][0].x = desc->a[0][aarx+(aatx*desc->nb_rx)].x; - desc->ch[aarx+(aatx*desc->nb_rx)][0].y = desc->a[0][aarx+(aatx*desc->nb_rx)].y; + desc->ch[aarx+(aatx*desc->nb_rx)][0].r = desc->a[0][aarx+(aatx*desc->nb_rx)].r; + desc->ch[aarx+(aatx*desc->nb_rx)][0].i = desc->a[0][aarx+(aatx*desc->nb_rx)].i; } else { for (k=0; k<(int)desc->channel_length; k++) { - desc->ch[aarx+(aatx*desc->nb_rx)][k].x = 0.0; - desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0; + desc->ch[aarx+(aatx*desc->nb_rx)][k].r = 0.0; + desc->ch[aarx+(aatx*desc->nb_rx)][k].i = 0.0; for (l=0; lnb_taps; l++) { if ((k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset) == 0) @@ -1842,8 +1842,8 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { s = sin(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset))/ (M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset)); - desc->ch[aarx+(aatx*desc->nb_rx)][k].x += s*desc->a[l][aarx+(aatx*desc->nb_rx)].x; - desc->ch[aarx+(aatx*desc->nb_rx)][k].y += s*desc->a[l][aarx+(aatx*desc->nb_rx)].y; + desc->ch[aarx+(aatx*desc->nb_rx)][k].r += s*desc->a[l][aarx+(aatx*desc->nb_rx)].r; + desc->ch[aarx+(aatx*desc->nb_rx)][k].i += s*desc->a[l][aarx+(aatx*desc->nb_rx)].i; // printf("l %d : desc->ch.x %f, s %e, delay %f\n",l,desc->a[l][aarx+(aatx*desc->nb_rx)].x,s,desc->delays[l]); } //nb_taps @@ -2123,7 +2123,7 @@ int load_channellist(uint8_t nb_tx, uint8_t nb_rx, double sampling_rate, double #define Td 2.0 main(int argc,char **argv) { double amps[8] = {.8,.2,.1,.04,.02,.01,.005}; - struct complex ch[(int)(1+2*sampling_rate*Td)],phase; + struct complexd ch[(int)(1+2*sampling_rate*Td)],phase; int i; randominit(); phase.x = 1.0; diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 78e260b73f..4b3ac5f862 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -64,11 +64,11 @@ typedef struct { ///length of impulse response. should be set to 11+2*bw*t_max uint8_t channel_length; ///channel state vector. size(state) = nb_taps * (n_tx * n_rx); - struct complex **a; + struct complexd **a; ///interpolated (sample-spaced) channel impulse response. size(ch) = (n_tx * n_rx) * channel_length. ATTENTION: the dimensions of ch are the transposed ones of a. This is to allow the use of BLAS when applying the correlation matrices to the state. - struct complex **ch; + struct complexd **ch; ///Sampled frequency response (90 kHz resolution) - struct complex **chF; + struct complexd **chF; ///Maximum path delay in mus. double Td; ///Channel bandwidth in MHz. @@ -84,7 +84,7 @@ typedef struct { ///in Hz. if >0 generate a channel with a Clarke's Doppler profile with a maximum Doppler bandwidth max_Doppler. CURRENTLY NOT IMPLEMENTED! double max_Doppler; ///Square root of the full correlation matrix size(R_tx) = nb_taps * (n_tx * n_rx) * (n_tx * n_rx). - struct complex **R_sqrt; + struct complexd **R_sqrt; ///path loss including shadow fading in dB double path_loss_dB; ///additional delay of channel in samples. diff --git a/targets/ARCH/rfsimulator/apply_channelmod.c b/targets/ARCH/rfsimulator/apply_channelmod.c index ab8ae77edd..d7d3a68965 100644 --- a/targets/ARCH/rfsimulator/apply_channelmod.c +++ b/targets/ARCH/rfsimulator/apply_channelmod.c @@ -74,10 +74,10 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si for (int i=0; i<((int)nbSamples-dd); i++) { struct complex16 *out_ptr=after_channel_sig+dd+i; - struct complex rx_tmp= {0}; + struct complexd rx_tmp= {0}; for (int txAnt=0; txAnt < nbTx; txAnt++) { - const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)]; + const struct complexd *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)]; //const struct complex *channelModelEnd=channelModel+channelDesc->channel_length; for (int l = 0; l<(int)channelDesc->channel_length; l++) { @@ -88,14 +88,14 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si // it would be better to split out each antenna in a separate flow // that will allow to mix ru antennas freely struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize]; - rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y; - rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y; + rx_tmp.r += tx16.r * channelModel[l].r - tx16.i * channelModel[l].i; + rx_tmp.i += tx16.i * channelModel[l].r + tx16.r * channelModel[l].i; } //l } // Fixme: lround(), rount(), ... is detected by valgrind as error, not found why - out_ptr->r += lround(rx_tmp.x*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); - out_ptr->i += lround(rx_tmp.y*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); + out_ptr->r += lround(rx_tmp.r*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); + out_ptr->i += lround(rx_tmp.i*pathLossLinear + noise_per_sample*gaussZiggurat(0.0,1.0)); out_ptr++; } From 6091452dd31b6de951249abdadfb974cfa2a3272 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 9 Aug 2021 12:05:07 +0200 Subject: [PATCH 129/185] fix remaining usage of deleted type struct complex --- openair1/SIMULATION/LTE_PHY/dlsim.c | 16 ++-- openair1/SIMULATION/LTE_PHY/ulsim.c | 4 +- openair1/SIMULATION/NR_PHY/dlsim.c | 1 - openair1/SIMULATION/NR_PHY/prachsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 3 +- openair1/SIMULATION/TOOLS/abstraction.c | 80 +++++++++---------- openair1/SIMULATION/TOOLS/multipath_channel.c | 26 +++--- 7 files changed, 65 insertions(+), 67 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index adfda7a0c8..9a9ccaf1f7 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -200,8 +200,8 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, for (u=0; u<2*ru->frame_parms->N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].x; - channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].y; + channelx = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].r; + channely = eNB2UE[0]->chF[aarx+(aatx*eNB2UE[0]->nb_rx)][u].i; fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } @@ -213,8 +213,8 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, for (u=0; u<2*ru->frame_parms->N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].x; - channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].y; + channelx = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].r; + channely = eNB2UE[1]->chF[aarx+(aatx*eNB2UE[1]->nb_rx)][u].i; fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } @@ -225,8 +225,8 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, for (u=0; u<2*ru->frame_parms->N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].x; - channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].y; + channelx = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].r; + channely = eNB2UE[2]->chF[aarx+(aatx*eNB2UE[2]->nb_rx)][u].i; fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } @@ -237,8 +237,8 @@ void DL_channel(RU_t *ru,PHY_VARS_UE *UE,uint subframe,int awgn_flag,double SNR, for (u=0; u<2*ru->frame_parms->N_RB_DL; u++) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].x; - channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].y; + channelx = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].r; + channely = eNB2UE[3]->chF[aarx+(aatx*eNB2UE[3]->nb_rx)][u].i; fprintf(csv_fd,"%e+i*(%e),",channelx,channely); } } diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 0d39e6e533..20a348f6c3 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -1111,8 +1111,8 @@ int main(int argc, char **argv) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { // abs_channel = (eNB2UE->chF[aarx+(aatx*eNB2UE->nb_rx)][u].x*eNB2UE->chF[aarx+(aatx*eNB2UE->nb_rx)][u].x + eNB2UE->chF[aarx+(aatx*eNB2UE->nb_rx)][u].y*eNB2UE->chF[aarx+(aatx*eNB2UE->nb_rx)][u].y); - channelx = UE2eNB->chF[aarx+(aatx*UE2eNB->nb_rx)][u].x; - channely = UE2eNB->chF[aarx+(aatx*UE2eNB->nb_rx)][u].y; + channelx = UE2eNB->chF[aarx+(aatx*UE2eNB->nb_rx)][u].r; + channely = UE2eNB->chF[aarx+(aatx*UE2eNB->nb_rx)][u].i; // if(transmission_m==5){ fprintf(csv_fdUL,"%e+i*(%e),",channelx,channely); // } diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b597425ddf..63def357d8 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -87,7 +87,6 @@ uint16_t sl_ahead=0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; THREAD_STRUCT thread_struct; nfapi_ue_release_request_body_t release_rntis; -msc_interface_t msc_interface; uint32_t N_RB_DL = 106; // dummy functions diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 93bed5514f..78dfa9d9d0 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -216,7 +216,7 @@ int main(int argc, char **argv){ char c; double sigma2, sigma2_dB = 0, SNR, snr0 = -2.0, snr1 = 0.0, ue_speed0 = 0.0, ue_speed1 = 0.0; - double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs, bw; + double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs=0, bw; int i, l, aa, aarx, **txdata, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1; int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0; uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 62f4420e75..7cf927ec50 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -83,7 +83,6 @@ double cpuf; uint64_t downlink_frequency[MAX_NUM_CCs][4]; THREAD_STRUCT thread_struct; nfapi_ue_release_request_body_t release_rntis; -msc_interface_t msc_interface; uint32_t N_RB_DL = 106; extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration @@ -286,7 +285,7 @@ int main(int argc, char **argv) int gNB_id = 0; int ap; int tx_offset; - int32_t txlev; + int32_t txlev=0; int start_rb = 0; int UE_id =0; // [hna] only works for UE_id = 0 because NUMBER_OF_NR_UE_MAX is set to 1 (phy_init_nr_gNB causes segmentation fault) float target_error_rate = 0.01; diff --git a/openair1/SIMULATION/TOOLS/abstraction.c b/openair1/SIMULATION/TOOLS/abstraction.c index 7ac1980417..d19afcd030 100644 --- a/openair1/SIMULATION/TOOLS/abstraction.c +++ b/openair1/SIMULATION/TOOLS/abstraction.c @@ -111,14 +111,14 @@ int freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) { for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].x=0.0; - desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].y=0.0; + desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].r=0.0; + desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].i=0.0; for (l=0; l<(int)desc->nb_taps; l++) { - desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].x+=(desc->a[l][aarx+(aatx*desc->nb_rx)].x*clut[l]+ - desc->a[l][aarx+(aatx*desc->nb_rx)].y*slut[l]); - desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].y+=(-desc->a[l][aarx+(aatx*desc->nb_rx)].x*slut[l]+ - desc->a[l][aarx+(aatx*desc->nb_rx)].y*clut[l]); + desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].r+=(desc->a[l][aarx+(aatx*desc->nb_rx)].r*clut[l]+ + desc->a[l][aarx+(aatx*desc->nb_rx)].i*slut[l]); + desc->chF[aarx+(aatx*desc->nb_rx)][n_samples/2+f2].i+=(-desc->a[l][aarx+(aatx*desc->nb_rx)].r*slut[l]+ + desc->a[l][aarx+(aatx*desc->nb_rx)].i*clut[l]); } } } @@ -138,42 +138,42 @@ double compute_pbch_sinr(channel_desc_t *desc, uint16_t f; uint8_t aarx,aatx; double S; - struct complex S_i1; - struct complex S_i2; + struct complexd S_i1; + struct complexd S_i2; avg_sinr=0.0; // printf("nb_rb %d\n",nb_rb); for (f=(nb_rb-6); f<(nb_rb+6); f++) { S = 0.0; - S_i1.x =0.0; - S_i1.y =0.0; - S_i2.x =0.0; - S_i2.y =0.0; + S_i1.r =0.0; + S_i1.i =0.0; + S_i2.r =0.0; + S_i2.i =0.0; for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc->chF[aarx+(aatx*desc->nb_rx)][f].y); + S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc->chF[aarx+(aatx*desc->nb_rx)][f].i); // printf("%d %d chF[%d] => (%f,%f)\n",aarx,aatx,f,desc->chF[aarx+(aatx*desc->nb_rx)][f].x,desc->chF[aarx+(aatx*desc->nb_rx)][f].y); if (desc_i1) { - S_i1.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y); - S_i1.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y - - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x); + S_i1.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].i); + S_i1.i += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].i - + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].r); } if (desc_i2) { - S_i2.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y); - S_i2.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y - - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x); + S_i2.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].i); + S_i2.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].i - + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].r); } } } // printf("snr %f f %d : S %f, S_i1 %f, S_i2 %f\n",snr,f-nb_rb,S,snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y),snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y)); - avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y)+snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y))); + avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.r*S_i1.r + S_i1.i*S_i1.i)+snr_i2*sqrt(S_i2.r*S_i2.r + S_i2.i*S_i2.i))); } // printf("avg_sinr %f (%f,%f,%f)\n",avg_sinr/12.0,snr,snr_i1,snr_i2); @@ -191,42 +191,42 @@ double compute_sinr(channel_desc_t *desc, uint16_t f; uint8_t aarx,aatx; double S; - struct complex S_i1; - struct complex S_i2; + struct complexd S_i1; + struct complexd S_i2; DevAssert( nb_rb > 0 ); avg_sinr=0.0; // printf("nb_rb %d\n",nb_rb); for (f=0; f<2*nb_rb; f++) { S = 0.0; - S_i1.x =0.0; - S_i1.y =0.0; - S_i2.x =0.0; - S_i2.y =0.0; + S_i1.r =0.0; + S_i1.i =0.0; + S_i2.r =0.0; + S_i2.i =0.0; for (aarx=0; aarxnb_rx; aarx++) { for (aatx=0; aatxnb_tx; aatx++) { - S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc->chF[aarx+(aatx*desc->nb_rx)][f].y); + S += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc->chF[aarx+(aatx*desc->nb_rx)][f].i); if (desc_i1) { - S_i1.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y); - S_i1.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].y - - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].x); + S_i1.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].i); + S_i1.i += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].i - + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i1->chF[aarx+(aatx*desc->nb_rx)][f].r); } if (desc_i2) { - S_i2.x += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x + - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y); - S_i2.y += (desc->chF[aarx+(aatx*desc->nb_rx)][f].x*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].y - - desc->chF[aarx+(aatx*desc->nb_rx)][f].y*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].x); + S_i2.r += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].r + + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].i); + S_i2.i += (desc->chF[aarx+(aatx*desc->nb_rx)][f].r*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].i - + desc->chF[aarx+(aatx*desc->nb_rx)][f].i*desc_i2->chF[aarx+(aatx*desc->nb_rx)][f].r); } } } // printf("f %d : S %f, S_i1 %f, S_i2 %f\n",f-nb_rb,snr*S,snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y),snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y)); - avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.x*S_i1.x + S_i1.y*S_i1.y)+snr_i2*sqrt(S_i2.x*S_i2.x + S_i2.y*S_i2.y))); + avg_sinr += (snr*S/(desc->nb_tx+snr_i1*sqrt(S_i1.r*S_i1.r + S_i1.i*S_i1.i)+snr_i2*sqrt(S_i2.r*S_i2.r + S_i2.i*S_i2.i))); } // printf("avg_sinr %f (%f,%f,%f)\n",avg_sinr/12.0,snr,snr_i1,snr_i2); diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c index cab812b054..3045d8ca6c 100644 --- a/openair1/SIMULATION/TOOLS/multipath_channel.c +++ b/openair1/SIMULATION/TOOLS/multipath_channel.c @@ -183,32 +183,32 @@ void multipath_channel(channel_desc_t *desc, for (i=0; i<((int)length-dd); i++) { for (ii=0; iinb_rx; ii++) { - rx_tmp.x = 0; - rx_tmp.y = 0; + rx_tmp.r = 0; + rx_tmp.i = 0; for (j=0; jnb_tx; j++) { for (l = 0; l<(int)desc->channel_length; l++) { if ((i>=0) && (i-l)>=0) { - tx.x = tx_sig_re[j][i-l]; - tx.y = tx_sig_im[j][i-l]; + tx.r = tx_sig_re[j][i-l]; + tx.i = tx_sig_im[j][i-l]; } else { - tx.x =0; - tx.y =0; + tx.r =0; + tx.i =0; } - rx_tmp.x += (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].x) - (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].y); - rx_tmp.y += (tx.y * desc->ch[ii+(j*desc->nb_rx)][l].x) + (tx.x * desc->ch[ii+(j*desc->nb_rx)][l].y); + rx_tmp.r += (tx.r * desc->ch[ii+(j*desc->nb_rx)][l].r) - (tx.i * desc->ch[ii+(j*desc->nb_rx)][l].i); + rx_tmp.i += (tx.i * desc->ch[ii+(j*desc->nb_rx)][l].r) + (tx.r * desc->ch[ii+(j*desc->nb_rx)][l].i); if (i==0 && log_channel == 1) { - printf("channel[%d][%d][%d] = %f dB (%e,%e)\n",ii,j,l,10*log10(pow(desc->ch[ii+(j*desc->nb_rx)][l].x,2.0)+pow(desc->ch[ii+(j*desc->nb_rx)][l].y,2.0)), - desc->ch[ii+(j*desc->nb_rx)][l].x, - desc->ch[ii+(j*desc->nb_rx)][l].y); + printf("channel[%d][%d][%d] = %f dB (%e,%e)\n",ii,j,l,10*log10(pow(desc->ch[ii+(j*desc->nb_rx)][l].r,2.0)+pow(desc->ch[ii+(j*desc->nb_rx)][l].i,2.0)), + desc->ch[ii+(j*desc->nb_rx)][l].r, + desc->ch[ii+(j*desc->nb_rx)][l].i); } } //l } // j - rx_sig_re[ii][i+dd] = rx_tmp.x*path_loss; - rx_sig_im[ii][i+dd] = rx_tmp.y*path_loss; + rx_sig_re[ii][i+dd] = rx_tmp.r*path_loss; + rx_sig_im[ii][i+dd] = rx_tmp.i*path_loss; #ifdef DEBUG_CHANNEL if ((i%32)==0) { printf("rx aa %d: %p %p %f,%f => %e,%e\n",ii,rx_sig_re[ii],rx_sig_im[ii],rx_tmp.x,rx_tmp.y,rx_sig_re[ii][i-dd],rx_sig_im[ii][i-dd]); From 78f3bca19a5585e990496aa4fc514edd3d413766 Mon Sep 17 00:00:00 2001 From: Rahul Gottipati Date: Mon, 9 Aug 2021 16:36:27 +0530 Subject: [PATCH 130/185] CSI-RS handling in nFAPI --- executables/nr-gnb.c | 7 +- nfapi/oai_integration/nfapi_pnf.c | 43 +++--- .../nfapi/public_inc/nfapi_nr_interface_scf | Bin 3986416 -> 0 bytes nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 8 +- nfapi/open-nFAPI/pnf/src/pnf_p7.c | 2 +- openair1/SCHED_NR/fapi_nr_l1.c | 128 ++++++++---------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 17 ++- .../CONF/oaiL1.nfapi.usrpx300.conf | 2 + 9 files changed, 97 insertions(+), 112 deletions(-) delete mode 100644 nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index de24bb9136..7a8ff0dabe 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -142,7 +142,7 @@ void rx_func(void *param) { int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - LOG_I(PHY,"slot rx %d \n", slot_rx); + LOG_D(PHY,"slot rx %d \n", slot_rx); start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* @@ -253,7 +253,7 @@ void rx_func(void *param) { stop_meas( &softmodem_stats_rxtx_sf ); LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx); - + // Call the scheduler start_meas(&gNB->ul_indication_stats); @@ -265,8 +265,7 @@ void rx_func(void *param) { gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); stop_meas(&gNB->ul_indication_stats); - - + notifiedFIFO_elt_t *res; if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 520a5dc578..5957f173f3 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1216,13 +1216,12 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, int sfn = req->SFN; int slot = req->Slot; - //int slot_tx = slot + 6; // ref for PNF is slot_rx, so increment by slot ahead struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; if (proc==NULL) proc = &gNB->proc.L1_proc; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu_list = req->dl_tti_request_body.dl_tti_pdu_list; - if (req->dl_tti_request_body.nPDUs) + //if (req->dl_tti_request_body.nPDUs) // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d; sfn:%d, slot:%d, nGroup:%u, nPDUs: %u, nUE: %u, PduIdx: %u,\n", // __FUNCTION__, proc->frame_tx, proc->slot_tx, proc->frame_rx, proc->slot_rx, // TODO: change subframes to slot // req->SFN, @@ -1233,27 +1232,20 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, // req->dl_tti_request_body.PduIdx); for (int i=0; idl_tti_request_body.nPDUs; i++) { - // TODO: enable after adding gNB PDCCH: // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sfn/sf:%d PDU[%d] size:%d pdcch_vars->num_dci:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size,pdcch_vars->num_dci); if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE) { nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu=&dl_tti_pdu_list[i]; - memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); - //if(!&dl_tti_pdu->pdcch_pdu) handle_nfapi_nr_pdcch_pdu(gNB, sfn, slot, &dl_tti_pdu->pdcch_pdu); - //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? - // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); - } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PDU:%d BCH: pdu_index:%u pdu_length:%d sdu_length:%d BCH_SDU:%x,%x,%x\n", __FUNCTION__, i, pdu_index, bch_pdu->bch_pdu_rel8.length, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length, sdu[0], sdu[1], sdu[2]); - handle_nr_nfapi_ssb_pdu(gNB, sfn, slot, &dl_tti_pdu_list[i]); - gNB->pbch_configured=1; - //} else { - // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() BCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pdu_index); - //} - } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) { + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PDU:%d BCH: pdu_index:%u pdu_length:%d sdu_length:%d BCH_SDU:%x,%x,%x\n", __FUNCTION__, i, pdu_index, bch_pdu->bch_pdu_rel8.length, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length, sdu[0], sdu[1], sdu[2]); + handle_nr_nfapi_ssb_pdu(gNB, sfn, slot, &dl_tti_pdu_list[i]); + gNB->pbch_configured=1; + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) { nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu = &dl_tti_pdu_list[i].pdsch_pdu; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15_pdu = &pdsch_pdu->pdsch_pdu_rel15; - //nfapi_nr_tx_data_request_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15_pdu = &pdsch_pdu->pdsch_pdu_rel15; nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; if (tx_data != NULL) { @@ -1267,14 +1259,21 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, LOG_E(PHY,"pnf_phy_dl_config_req illegal harq_pid %d\n", harq_pid); return(-1); } - //uint8_t *dlsch_sdu = (uint8_t *)tx_data->TLVs[0].value.direct; + uint8_t *dlsch_sdu = nr_tx_pdus[UE_id][harq_pid]; - memcpy(dlsch_sdu, tx_data->TLVs[0].value.direct,tx_data->PDU_length);//TODO: Check if required + memcpy(dlsch_sdu, tx_data->TLVs[0].value.direct,tx_data->PDU_length); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols); handle_nr_nfapi_pdsch_pdu(gNB, sfn, slot,pdsch_pdu, dlsch_sdu); - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(sfn,slot), rel15_pdu->pduIndex); } - } else { + } + else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(sfn,slot), rel15_pdu->pduIndex); + } + } + else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE) { + nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu = &dl_tti_pdu_list[i].csi_rs_pdu; + handle_nfapi_nr_csirs_pdu(gNB, sfn, slot, csi_rs_pdu); + } + else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() UNKNOWN:%d\n", __FUNCTION__, dl_tti_pdu_list[i].PDUType); } } diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf deleted file mode 100644 index 6ee4ec840431454c5429456810abaa7a2f29fb59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3986416 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 z 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°XK?cs+^}VF8F+= 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�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
=(V8T~( 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
~j43GSco4W5em#vL_`zqm_oUE=(0 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

^SLPfJk$!O%IyUB$-;YTl z&PfS&S?Qp*#e892m>Qe(r|Chl1ekEhifP)3x(s&yn=CBp6kN5-RXDO|B zx0jFyCsV9+2<*b+JUoxs>fmQTYW>3hhjV}6@rYK(xS+%4DzAR2;Rape=2Lt(Unm)% z;fCLF&R6CT_EY`sy2l#Lkv`&_lwg;Y-BMQRdC8#b4~&yOP5{C=WM#M1p?ZGy&5P%r z#vY0K&=}`Ba4skLNSuT`wbsZbH*5N;N!U&10LMCEURBYt3Qul3FQI;&OtI2e`5(ru zj=;WqHsyEelVnge)y!>DtK;=E$S1q)dm^am5Oeulytf9n8|3Sq51yE-;YvrH+f7Do z*&GA^_9?yI^++KrSmF9rj0<^c`HGoGHGRWL=*wf`M>7i07jPe%nuDTm85wO#!E?_2 z49;hZd<6HmD(JvVt6MMA{8vqaugrp?y4*mIznLS0Ri%eHCneZrrLVeM=X>A3-a#7Q zm`lDA`93Ddb8g&r=LM;M0&<)~R(vJud*DXA-?6pES4!e@Niyep5z;Rp-}&*e@k^!l zoRbpl()hCLzcT3;u-;ej(EUwVh%CYN-@Mv-d>GYWz$>*_V4J!XUxniP=Fy8No*7HN z1HQ7cNxY^|T$_`)~t zK-__GXiCQ;&jLJMQatwe17x}Z+4hooH~85n3(90k4{=UPu**u{7~u>3V*C47qV)%3 zDXQV@zCYV9iYXnQc>Wbgdkn=Zs6!TdBcShP=SpfOVMh<-WTpJ#IWfo$BoQK9;Xc_<}zS9{lOu zMpQ}4sATWIY#XRYreYl`qU{HzW~P3ed)l6_3_wiDApHX7-J37}?S%9UbAnCPs$cjh z9iBgX5ackFfCC+5LknDyDZ7=gx$>gaz<5%j>g@hJYd1gP3wdANj7+rtYb>fDUu8bF z8wgPJ>G2g(wh_1Fpfi79`Nl|pgZ#JS4+}dRQPDN8v&WU$MyMX8#`&S6{$3%yYCK6k zWRD9iSiS*O*Wrp^dwgj`MQbRvoyAGEo&P+}N2{U(H|~6Wu$HI#mnD~{vV23tA7Fgz zv;E5r>~(Vl_06RF+y43|MelF2d?SP}tP@P??lpbRC*puFyhj#SCAcsiKe&JPIXH(d zg${A)Hn5$yM_-3&vGgT$6&y+Ax18HeW-e~?of=j#F4(Q*X?cvc zUwidA_FnrS6dG#yy~ zEhhd8aeb%UGst3Q3+fOgI+R6#pPWaZlR*BFOtIqYK_d_73vuVWN$pWIHkJZGzFCyM zJJ*jmA~iJP1{{8FhSgW5`1Wn^;~66=`h2VdzR-rn^%7iIe^~qFh(j!{a=q<1WXd@J zBOg6)2Ks`ZJ+kG4Be0Jyxvz+gL*bSf7xJiSbD#c$#&oi6pal>8oeT@LtOQMYLg z_IR+S*mxWwc8kxChoHEQ`Uzcf9Lz6dx&hhFCAiSv3V$!UD8ax%l~5GxPwg^nf)27_ z53Ym>E{w;%iJh*HZseSlV3(D?k>_xKgK;Qw?U7bmex|z2&pf;Jemwojd)7&xB_PK+ z1bpjp_RAFRvvd2OkOG{O66~_lH;>YH<8SEmI8P=3;T*EU^%B0&k2`j0bWnPV(>TE{ zE8HA(KpWqlf4Sm9>4^j&oI_T)0g_ik{N3Ee-zxq9H>bVTE-Ty^d2SFm7vJ&mAJXeq z2>kt4xalPBz&QW-*cx4=bbfoQy$F|^KSW9X0R8yx1?c%5reut<&mUx_4OA7v7xIU+ zF&)ar6Kv|dygTgUx=fv~ZAOUyf)10K44){WdNRdI-w^SK3J9!s#k4ij8_A&JXd-i( zppSo+`tOpRAIy-Na863F%Zjf;`WqN^%-X5_q^txWoI_T)1w>!)hdK4o>>I5>BvSyF zSNvo=hWlhA53WFJ8%s_-vGF*A^0S_|4!#V&zap7pr9+hH0ORKGFgt!R8B}Y3@Kbhs z^=RHu>7`49>!aescb&_glU}|wxS160y|*J=Q%0HiI#&ATq5}{kAwC@Wbmiqz)5JLJ zQ7hb>UOMit@9nr;dWCJ7xNe0TBmMw+$%Q73Hb{`DB~h$!{X}2rZ`W@`$xb69XrBFg zDmSkCI$<4v@09$XCmK=F{B(=m5nuKfV#?imAS_{pQ%e(g2KUI*<|!>gD4 zP6dR=n&)S4*5)lrH|Oih20&6NA$clk%rh|Jr2zebNH%X_h;!_!g4!7&`D{^Q`%idcD~QmWwm0Rq|N`}ZKL zVN1l`an~;*L$SUv&-zWiCWF0pYJsf|xXChOzmR(AcIz;I(h?RoQ_yZv;=hph<%Oc( zOUqg0#C6So^BBHfG7f=J)wvJBbjwhpf_ziRx+lbkrY$oTNGlAmwiS(U$#SE<3dOhg z#K%p1OYHe_{WnPb_cFw6kk?EvHb*S(1nXdbfN|)qzDjTDCNp-TJ(>>eIZ@)jkWaQ6 z+rl)?r*{w*f{AY{s8x# z&R;dWItvllZrhK!{s8N6Fm8g~{_eNz9E&SAbr#Q9zN(6G!Es;sqPl5yQnlyHQi<2q zX&4v$;Z}}64z z|A#%v@8I`&*)~wmA@L02q_hv+?}k8;M6uE#MCq_rQX z+b_8BAxz~v_iXgV<)E>B%WQG!(@VF#l%I7A9N8e5o>VA3mAhf3uS)cV_;4mT>T4vm~B@~jYDlYaVMv%nE$F|z6mpcjMY;@+?)6;8LDojLzL(M>jbC!H#CiJ5qm%5 z`a>S^2bj0C`5HzeWAWB-HeMK8p*7##IG({py9{~pE~yrKM&i1a4l$wwFzx$UWD|>0 zEa(q~O=>Z-|e_Fz+6|bk{=moSe#n{!8=)KfCpCgE5lK zA}6j}>031XV} z;Ai8WTW8Wi+94JnLgaVXD0fnaxu&cZi@#AB`%ygv_}qzC&~yvGvv8941K4ri zL+KEUOs&T9O>?LNiz^dc$fIiA_e47uH`^gD+pdWG9_tP0z>_)unw}esRIv9mh=r!I zNB4)>6CeAYJsv2q$Avbm4qi%!dF`Gv=@7Qpfg9IV(%)bn+o@a&Qyx`tr9EGs4zV>@ z2Uvel4{h23?};wOVX=57y{6+{_hh#_X-wD-US-dhZ3A`hy?A}H5!zmOVGvsNB0WBd z@4e;e;3571I_!Gp*LiR)x)j;_1J`Z^#BMO(lzV<=%Fj|8+v~vPy9kd%*CE__^{Pi` zuCSdt&E9T2+~7cLHyDRb{xBMN zJns~Xo7u!(UueVj;{f3c7k#kllmZr4vFFP+iPz=(vE3jq**?EvQ}(3nN@9Fv^hgO{ zf}iz>HJ{7kdY={>hx{^L--K!A&Zcj|?GZysxlzo|ir46V_QxgkvmoVXdye|n8OWka zmc8A$eio(jo$EM$mMgdplSbL?9**6zvh3}~>&Ma$y1pk|=*#L?)CS|0MF*Pwjpp4+ z7A-!o&7#vVF63v`ej0XxJ?^nP?*1n0zkbSY_jBwP zyv+i+5T$UZa&W_< zxKzG#@?iEoTKo+Ua%Z;yWw&u0y9L^d+09Sc?Ou-Ef;+|ZRY-pWyM;OW7CY3J_1|nt zhY(MPG%+1ADZVo}e6tRV=}@fddEZmlG%kJqOil86E>?#irNajt9g3c@=gW&{0Wyz; ziN!qsgB{RIQbmhrEMKV`)&b^2<2if-4*2qj1gN;)WK5O&*>f^~6VoAw=m7qE|9chg zW^wK6nhxxF#Uwt!cwBu?lQ~*^2)c~xIg~$q$kDgBqkX^N`GZ2`eWzXIeXI`BD(nxS zL!TKJr)fG!54nqzAxeh{938?AbTDy6J3NH%wP<_I{uZcTU<-#`+RX>p=nwkEM;yLs zf_%eNJge~Pun>Ybl)_xGe&MJ5L2)r3GLS(Pndl4aeS=m-KhyM8UFw@l`NPK?eRDe4 z_Y0OQ)blBQD{}PBnk1%gfYP_lCDhkT>HD7l%x#*!F_-#=DSan$^o!I#5ES_0) z3u^;)vY5VpYF;>W$fcVP)@p4!rR#NctO$Ln|(!KSU^h z*v8RU5%h;5N{2%n9SWz5>7e|ekH^mp67LtRT_U8vL0ljHh#q&86Yj?Od`jQ#9DSpT znE&Rq#5#bll&$rR&^jWkLA?H-zOHeYW4F}X?Cl0PY(Mr>{rG2&4w-^Fq*8o;=kQer z*{?_ObnxuJ`hq{a_Ta+R+Bg(+=?^O94?8$IWOTOo2VQ*eQT^gI7x97BLMG3zL+LN0!oLS932Xq+3Ub^g}O?ftAO>h4e9UR!Jd;F(_<3~o8=ODDb8VqxdEGS~{7<^eqta30tF1o_{@VPUf|@V(xy1lww+TZ| zqjmc-h&g)B=v{YwizvI@aKOwrP0((BD&P6Ib!z80S?XWOT(N$kQt@|%i~DaBmH4K2 z2euomM{T}s?I=xO>7+Y-iz$6?6K!F;~&nd(om$FmlQ`B{|mv;3jr;}FZoNBP;nEqeS_ zTOe&y(@y0bweCD02zdJ%iLZ zw5qKhC*>yY;$(=L2i(N5TZzN?!1{xa^0OB?ewMn#{`)<_W-P9U^0R6jzIhv*^$XS? z3aNbZxfT=7v&W?+V(~0S#k2P>;kX$f@eI}<8s61wsMarnF5_7$rEhhPzWEOOF>AL> z${$|h_(Q=v&emaAT$$oqgTq(dDCQ5!y*R$4BYhWN-{DnFUnR-@#`;k)U-y2@-brDgS+$FcHRy@sQ2`gdaf8z%k>I?VY}*C96B-T0PH>F^Lo2g#uhtp9o&>3QEP z9Dm4LB9=!f6yLr)zT3s@mU2;Fw{O4X@3&b`RF>P@jhF98zhE7}ZjZfo>GE}z@`p|7 zhu_!wg;ea$A2KL?`*HLw*@n z`su_UVEydYySt7z9lyukAJ{ffm&xzX-h{Sy`U^)RyUA!%Qj_@oZaAMUCGD~Q-iQwT zRcZ28%^#FD$;|^;eIr!<+n=MaPf*_|wSLx`qi>$W&r7p>1E`~E^Ue93xDyuqTyuns zL*Tz_Dqp)u(^vW?x&Fr5ExnIE9;b73$X;ddXT1IvKr3;e1H_%iE}n~L`Nl}x0UZ`s z(sfXi9FJLC9~FP!n6=+@-zg~gdEP973-`0yZ~otK({&x>XFPp9Yq7qN_Z?``=O~M7 zSJ&bhdtQ)=JGs-}H08fVg3rB5J278axA)z75`9hrGYBRzUhs7AlJO1ZS>?}%zhmEz zUEN9t55>339Xelmx8wfC{XAKu1nU3?TYOlyD$CE`TI{(MnfL?f+h_l@K`gFaUDJV$ zXF)2SE#kzpoMHCkG4I+rNA>ZdZR*_HOUEHHKJnVn`!v4vKG;?^V1429WDjvZPnK85 z8DCb197>1993AABZSBVO2bJ=No6GH}%f6qC9nSJpww*%7hwjHGqhI4pu2|`tdl-NJ zB#iTOipCvbQDc`m)0b^m)KB+^JCx_qJj+<}+S=-CY(Q!<`Tg%&sD4e^zaG*2OiAK* z!Fh(uxDESRIfQ#;^)-KRFP>nhrZ4MfVam^za{MfJu)PjEzQF~0zgThh@tYG+;~vuZ zvIn!P<8?w9-~K7=Iz`hr>{4GpiR;jhE6uEQ8GBv3y2h8)H$v(A7f0X1SH=8SS%=4k zR77mj#~V=AYApUM#BkL^*lsYsRUe;&@)G>cf`2(4hvGz79r7t1&Tw=nc){M!jPDTF z0@OIPVfu)^ymJ!m)9l8cQ%L*_;?9*_r^PfsizVS_EGE=bAI5P9P2;2y-(O++-h-?T zVmjp3(c?pK#g{A_dYIx2fSFGGxPkXk1gKJAQ`#kH$j*{x)buI~>W`ZU-4 z*S|D5|219zG;UuF9T;@Cbc^N>3i*9q)A`H}#FrN)rF?V%<}DC#wwOj^^f}Cx_VXd; zQt@iIFOHMoXE)vSTSNAo+&dH74RzQ5mtti%X^kGw3Y*^2HQ9?>;f9Exf%uP}sQ%`q z!i{BMKLgtxO1okyi<{9%?EXa|6(`Sf;$+4fVsSl8bbxv6+KTnxX8GFHt@Mo%|A%qt z?Nvk3bH!z3w26MS!d-t0k^BMX7t=SsJUWh<#6K&(CEfJ+aAUV#V_C?6gXd}4Hc*dH z`R|Nxt2gGIlW3pDmmN2YD1SK5@dr6u%pXdK|Hjt|I+gh!%dN1;S=?dy7E^pLaQONJ z$N6H)AJTU|0AV<(qUp;vDr%48Bs_mMan7&1*yDC}D_rkh9M@sJBqeRh_jWk!aVuOO z!G-6ePIqo{CEL!fZiSoCNY5YI&Ne@PCW@O!@)8)|e!ch7eUD4%g0Am1gVX~dT+ghZ7C)Z)4z3rD!>z#!C4E*7$Nfml%?=0NR-S{Sd ztLHnRuYNF+TH(teDv(h(A;uZ>I($BrGg7_e#O)2QoZVI{20P$?iuBIrBzzpQS-RUc> z$L(Pr&|`cU%x5TBcZ}U4w=7SF8zKneFH=XG#!v0|L|YP zOXAm-54+PLO5y`Nr||OP%0m#Yj5ej9%W+dZh;@K*=*SpwU(7e?(jQ_}UQ)F0K?Gbz zM&Ock(VY(An9lc&r&qkK@eL=*mmS}HRDXMe)8F!674wHE(HHXH^7Y4d)cC4N@&)PW z5{Y3Q0JnW;L3<5XcKLiscmlQ$+%UcNkwfS|_6Mn}JG+&zXm8B_G0p7*)r8&1{dLxbLX zVwJ`>=n^+d;r5S&p4V{0E^!qyAA-1k(;FSN=@>{HFS#F!&0`B|v&HEnkX}F5ZxFexZ1APMW)G6VstCZrFxZ@kDiu(m%|8ZN(yER<@ukLXD zKHQHHQEAx1SyA+2D8WgB{!8(lvG3c?rF>oLAm60xu;b3dX#D~EuivHJd;}Nz#djx` zmCjqjF8QXB=T^XOPam%MoyJ#ni5sN&_I&$@zZBPHekK$Dh4EM#K4iIuEC1`x&%6W| z)>FTjFk-!itGLAVRMY+8^~rzs(QtzF8#Bm+Qp^v^8uCixjr8>LMz_yFtiQ^8$ z-wCVx&Sa0LKId${$+inf*dJhi(f0Pnx$JSJidZ}=K8E=M?o-n%pk*GcSXfH#d1aQ5 zcNE5j?~m#}zV|lvc$U|eFLz#;qG12M3<19J4vUJ`v)kC>nj4`#DaSEih-dwe{3o#uc8}xb04PgmQGYH?k z?&73c9e+NyA!3L~u~CiVwm4dYmk-`4w7iPp(+u zh9Ac|coAH7mlY^J5Phe*(;@m2<_q~*jh+v;VcDjR5sPO9GLAb{5MYC&&L-0z@C(Kv!MTW#`-o#fZx5|y_bfoOo_ZZdbn1zezmfjqG0<# zzFv3sJuv+?l)~4<;(DwMjspNVY*NpE44_ciBZeEOjqL{U_te&Drg2CSTrbHdxZn@X zPG2()DAGmwMU1ah7V7{v(0ko~u!zQl?T{dDaT$HwTl+G z{CU%qR9jr`_!dK%KlBS2-#Vacu%)=U7;b7^jC(l(Y?JllMHbipzF2(l5*?r)SLZxu z9<=}b5LbsHqC;7Pi*6B`irmsx2U8o^QM^dE+vsY)jnLw+GS*%E4c5Yb-vC{s{-lzj z2v^?(E4SgJ%l5xPV=^#0O zP8YpXbBU4lp?Lm~y`c2Ilk5^VQUm(~Z?W+>s9^iFL%6;Eor0zrSTTQd$96+4%_T_u7uGc%J@g!+T}DQmlI-&S zP=x9ixAuzm)o>Mu&xu+2L(a=MPJ%x?+ILkC;7XU=T(LMQk@XTV*b`Fp8;!5uC0`GD zUJmm0ltm@KYPhn?=QV&xhURCF*G$ zA7CDP-{H4!iGx!A0)o#KD?~@oq0anr(=;7oE_DbHyFt!A@!i3LHC)-{^Dxq{`16H; zTcP9mO_T)j&HPWr{8#CM<2u;w@zY3?$1Acv2a)^uJilzTpiLC-5;iK z{2{Bqtv^tz>6^hvalQz7N%fYwbM+&5t7y7dob)u%^WUs_vj%87gq`~XOC?^JAMT{klZFA95Q}J8`e4c96|NqA&PaeRc8O8m^M$=Z{(B zTUnjzZCA8PXDo%2#pZ7j zN{3H5Iute(U9 z9k~5CL%}+r8@$q6lUi3`-+9rawzzDQcs+0k<06Tbk1{Pg*P~}8~Z+e#Lpm~ti7ksF^zA~CEo%ve*@fiuWD(EJ2}(D;!c>-;WmyA zLHqmjtOW6TDtYb-^zFpKRjZ2Wn?>}6IJv0eKy-TqM<~^~zTA8#O7)ArJIwte@0i&5 zmQVBryDdBY1q`2tQglQtPReK{PFpXzdPmPc44@7wR(VNw2aF5%ogUi1)^x|vGeT?~ zCYQ>i&dq*WgfI79MTx$U_f6wG-9;8%2gHy%8Eg1vaj7+YMnNxbeQ>($^7 z`@8ir_2a@5Vt$rK^t}w>4n(U2$rh_|K0fJ&&CGg_#SPVVrY}2g zM#y*p^Q;Lk&705S<_kWD7u$;GComr0(yrn?EUwq#_e8SoB=TGv+;6#Z=^xi<@k}QB zP3JQ^tn3zOi^l_q5hv3Io8~Q9YsC6-DtS%};_tb}845#3D!9d&-Pm^00o>nUoL~3$ zTX$$WC@yvIQhcRdqfP4?C4zR#r~1X%KHr$;o2K{2?69(19_bgL?<40rj%S)lYF#mX zW%ArMjK>}1JN9b&`d#WPufukO=Yl-Vn%C8E<;&fz?_?0WL0y0lw1rSGO|RzP?+ zl%U{qLFvTLu0v?eT3`90#y9MeZ|o!8&o*$LgZ9;T<`4emw;0y9!(?3=60^38?la9> zGG7w&hY+RjPL960f}g)AA^C3=#P`Fy?lsM0Qv}yx@(5qRJuz>^YV=|#{&Z*h8XBRB zO6(5f<_%q{t!0mA>=Mg&f>eJy?@3+3;!1tQ_OSld<(zF>vEv) z#g=A$vjzF45xy|ak9~UG(=1=lZZUloN{2rV-2!3FQ2c_p>8o`eUYu;!AuChNZlUoQ z7sj`R9Uq)vAd4yyLB5eE^te9qocVjo(gnZ&S0()o#e(vsmfS=?aH4*NHmX|Fz zkVTd7`(iqTi4I`5`5$jz%HkFa>JTLT0`&dqM0=E78cTXVF}}(+tRv{KYQ_$ftr?5@ zv>0xXjPnrB?%uce5hE)4K03kAp#&+uP41mHnZ+%6MU1aZJ~xw!0Qc5gK83~g?iGuZ zc`fjG0sfFXGe5@SW(wlUujz5;4Ciw*IXBtrz+KlUK^Z!X6_=sE+tD@Hk|Owd$N=fb zFi^}{{q{W6k7cwe#hmwJF5lu#I^Q6NukUxU^)oNI&j5VWIlqIKVm~kB@-3nGj^XeP zJDeZ0>l#@oK!V-Mp}!#KdwtUHv-Mvt-%t;X3kw8QOsfRQrv>MmKFWU^o-%*#D_wB@ z=BIF*b8sd5c>q@jkAii$9O*Fb^A#7-i=kvaZrk4s=WCVNG>i-D8uxIX(=8cbi_7Jk zs_6dEZ{x3~^~qHGJc^4eQ@D?DaI>GZjM+1oT8v;5h*)w)I&_1x70&U06(&)Vw1wVR?~zVO`22+s36Ucu+N zaw&ZWaP&=^Eyh=>r|Ub7^Sr0;FDjK7dGfd4{#SbFxIThNQ4L~?BPp1s^ zG6ve>8hDgert5rHa`@)HD~20At>Z?oe%GW!(Ob5-Tpdz~|AG$t{xaVuQ&-#KmcDg* zBjunTCvzU0snW+_J56wY9C{HyuiP48e7m~BOl`gyZs&Nu$<-lC!TLg+T+8{qUa=tG z2o-nU=IG%2!B$@`-;|D+FT}|s_g|=mUJNCDq1f}vxp(0C5Ul_9xTWtm22fN$H8BbZJ~_H<#a=5POswD`-O zq)_wN5p6FActi2OF1B7>v;vP8u&}eO#<}keps149S!|var1(DHZ~H73H+P@yc)>P_ z*HcMB)Pwbl2g~d%5v|EJe3;9mg@>OWn)>wRkIuuZL zi?-j^-iV4m|0akVBe>Atp4oQ-mgfvbIUr`YP-E<8u#Q;$!1M(MP*lnL%yztBo5brL z@;fVVU!=p%#oO4E)Ky|}Cyn5O4z)gdov%tlx#dL@fzM#XpS#9gExM?fJ#!XKveLOx=;j(8~T>m;Tz6#L+^nGpqGv`^{ zG(jB#6yNuEFFelTdVdn*o6-d90Q&y4?}aTaZmKG#um5|Tm%zI6ktgQPD9uaAe)c+S z-D;fAAv!>Rt32m((@LU$gP0D|W%#)a7~h)jU;aAFC-{RHu6iZLh5W4I?7Be~H?&C% zH%4$FK=!C{c~2HMxLFKWCOX`N0Bco_DlBebtr)KK1#VXx0X~t^vmc9_8x_M1lh2LA z2N~u)e(rM?H)o3=E)~ySALNU%xM9J#Bj17NStz}ho=ZKjm&GmED#q7G^pz3dOCQ{r z$>L^h6T{6|px-|}+HC0aT0fRnJDwM^RN{3x1@{Yx4_*8IozI>W*&)VPzFx;|ooU7` z*eQma*Fn!89=*5gVwP`Kp)*`|-KdC)>&No5P4j@v^pI9Z&#xOSC+i`K6^Z4w-~N;3)UCrEpoWOsb3Tc;)aP15YP7IeRP=Rs|dzl ziTE!p5IlQdOIY486!m*CyG57k`j&052F*9|NEmk6-||U3L(A6E*cU6RI+wAe z{V2vagTx2$-%}@#WEoM>{lcGZ`Eu8zd}KWe)_?yyQe?XS772>w>%}O7Y3si)Pi%dA zsh`bo7uQqD>T$ABg`?nZh7uC|o(6RY<^}QW>QyUW(D+Kvy5p;Us;@_VeDtdSX}GG( z=XAs5c@2mUY2&AzFo=LE@=~$+W{?`+TCA^ski|`DAciXwyFp&vx?uTa7B?t(f2ff3 z3&8#HzCC}jxSq*kaYv=}ee>FJomt$xSz^@T|fJiFEl*uH73YcPQ`f?`0wY3u3oO;X|IKTF}_M2j9U!> zy|?mnnmIc#L0SRqo#RQNRV%g{LTfebG83!^eUFG z>hO2O*m-v@;S1~4({6j}NftNrkeI&3WPS|KRg7F--L%e?JyS5>q5NTe$C)O(l?d{U zk-Qql`Ra|@e5Z{=QpDXj6eE0LoNvdX8iKB;^ z);0V+#r!Nt#tX39nj6e^OPeA%URd|SzO?@a{C?rSQ!q3(Y{IqY%k9S{#BPwUcOAU(R~9!nEM_;E*bVfp z`^wSzn%!bvcjHi)^f%Dqhx^XKZ5Kl+EEMA#ruxP4P5&-6fTBufFR}QbQhZkrF!Rm- zT#ToKZd zZ2!BmDeuc_F2>hS@%{as%FEb`N9_4>^-a4B=lRet#%H&?mBmfX6YCd264zmT>vMMG zRu(t*gxI_#^-J6i{CD8pX~$Sx-+f|s^QPhZ-H?#{bnAzYYX0kYnV(6E_5OB#Oyk)s z-@s9^c~+SCLk$FYyY#)uw(3*1`kLARH>I9F4;Z@l(f?S!>I-6gi@Rfe;e!n2hW`F0 zi|Z47oR_;95Lhz&zl&E{~b+4`n#KFT&2}r3#oYtd~@H zWA7T4Z*YMvU$#lSE-QMRyludv(~Z-H6gf}vu3b2{O6 zunzOrh!HT{8%kzB+q{HpH-*GAFxa!b&2}rfAQpdpKJ33~2=~uXBU@c?j|{Ww<;H%jR{hQrs>M~rW38(oLDIJka6+#-r^ z4hI)KMCWMT-ZWk)m@mZ1v<`obXZ=CS6x4yjef{}!m08>pzis?wo5bsxBXGV0&%;c3 z{9E*RF`fq~cev|sA!0YsVK|4cPf!Oh(E<9!jI>Sd;%|cb7Z$_~m(%ALr#H1hF^|lg z<|U^C>kk=}-R3oV?rn-{d{cQy%pVkzSHq1rU%#JC>pQ6f#rz?Q;DSGlt@FES-jdl@ zjBk)Up9=ZpXX|FJj=y>8Ur-R&PreUGMp&Dc{k?^PjBiE-aTSvH!F(t@@VBp6+%)^& zVd9RP9`d{3d ziw`C~L$SU{04e=wt~owT665P5xUkN(v}MM>>~*~>#o|MR^kaDNw?U-coh)w2r(%4A zRDa9p*xjT_+YnRhOrpFsbYN96n))u zWBn^Ov$%G3jj!pvtMT{-4^+(Aaq>s@cc!qHt~V^kw}8Se^VKor9mWzB#4V<9f66~M(}*fbfoWoV^M_-9fIR9z`Pa~YV&OjS z;*Nywu)uRE*P_1<_T2^37ek3m7vn2GgL%RFLt}La%6~E6*mie({Z!sJuj|x216fol z{#=Z2h{CP@>f5idxCP&f`LCb!3s~J)UFYgPa8l{C4HtdzN`*;#BQ+uFywTOX`GKZ z#AW%Y6z-t6A2h9V6|NQ2!ACtm`E>b#^V#c`2tGgQr=H*W_xB~Hyf1gZvw1AbCp(Da z4ooyxrqn?F4fkX9OLzU)NAib;2>0#}*PG@S!OyUNvwXBViGEtO^fm1e{{9l^7kzU_ zqx%8I5}YZfgFG0=NyyhzHka*(USuP3;+hrTFnP`f`r8AaY&T)%ZWNmb6j#7@gV^46 zQV?#tn6S}4%cAjR`&;x%tOG1kf0Dl5rjqYHfV`xAnZLWB7ekTl@B7Ek zXZ-3G= z36+e;aDRSm%P*f{kNfhRjmK;|i9A0ExEnaQ1rBjpe@LbD-OJHI7Sute_=Z}Ub;z3K zOb3>)O!3{v;TyS0%x=;(c>V_ZR=dT_H{~lazG)QS{T#lzqWTiPFyE}+a`^A8zvKz> z^-_Fe9KPA){ylp=t*(u4T3vgU$^Cg4kCoLqcWL{zSC9Sk8u3$Ee^7`HkWjz>Q8-t_ z(_S;a7PDJArNaS^4#lE6bjJA?u*7-zg?W&{SNK@Yp?#GWUnmx4F7{P_O^HS5{GqwHNYw8?lxU8SWsPS0l=-~fW%+F-4O7qet?Rn(J55*Z zHCymGJU`I^*8Ap+9g?l#X|KU;Vt$rQ*{vQ&hrm*2c4PfFNa5D!;HHfhi)Ud@HA7aFAkoOH-HRoLoPkT+9?@R~n{Lb&}QQ4H%=R4%f+C^%vub=gq zw(54%ahn|)5mtvhN{4|Q9Wqup(}BfJC;2)&57YUkC-<}TG8c;3Ekf~qg2UIRI^)ao zk;#3his-<{`%ji-k4FXh=2Lv1m;?^WdV;P{5| zb*;#U__g@<#__t+zd`&p|8@N8djr3wyoHY!k$P|#-mhKV%Fl|a`1=$`huA7HyJZm_ zu0sS?)fu@`%H_rMEvER+qZWSL&C>>^TaC7I1#j}(Uwwr>8)cs@AD3(u71!s2qKlZ)^Zpx|s|9+ZeP#Gj+ zpLom2Hnu!?F}4~@nM93!N@YkIvG)7f|bD)w!#cpsjacZxbYEUaP&&u`Z3AmZkA_v!xfbW_E3J#V{> z#{-Rbv?o2KcAI+w%fNG3dY-~E_B@usr?Iq8$FkuuEE}g`Nq(YupgNTfAGV9Gu;EGH zUUO+Xm2ne!30JfOyD^I8bQWies@T`}yEXfg92?3bP+m7|`0u;Z7Hrtg|H#)UuU#ka z;wtib*IScUw1bz=W7+&T@Sg{ViSh>8Z#*81?Ca3Uo2?>m;zw)pit=Q2-?{qbk++A4 z`=hs8lUF=1$nC(^9|rIHOvQ7oZj1MyiS~8s?C@q4JJkPSY6s|XDt{3##xGp{*A`rH zCUaleFI?kyjiTHRY+d=1{E~|Mn0(t>v#)3em(C8hxs`cc`=6;D%Jid(i+|UMjVFJr z5)Y0$YLhn!35W7S>nifP%=1H4zeT;xe#=(zTVsv#x^?#5qKdqc8tq%ueJ^QZ-zPF; zcPfj&)Mj6gPTn?Ee2_g^Awid$7)ug(rzRgpLKN^Rp`#|3yE zlX=(vPiJ(Zmi`RHt;s8%m(e|^7OnD}TEXJ;WTM}EIy-D##SY#Y<2UX_zp?l|XU{{& zi~7Xgv}OlUUcXM>ZK}v?PuJ$RfDX596KSR>3XSXor9<|8}a9e=~p8CT~n9?`c)!P0TfIZ&l+g*PJXio7oKc2VLH;~}BL?O6pkd7kO|SyelvxgFSIhW)L| z@4Ti?wsv2P3h(rw^ot2{sU|6O)m@kJGunr zW!K++TQ~VIaeq_9)DERnD&*DK_qHnXx?VTMt!m$_x7oh-D)x1bHpQ(fZ(1ks?N#JW z)o5QAe_py1u>SAW_^~B&-G4rl=dfx0%zGMMCv^A0>wbZ=uypms(%%ouXaLJ%Z!8mM zV43w}Nz|0js7_`0RkSadLp!wd%E2w+eKQ}j_;^qhlsfysK}UblI>sA{5|F3x7mf2g8=b4@U{Lv>vKJwP|?J?4y_1H^+G zExrdsjNc}m9hOwFL+l+>d8_)(rCZ;5~ zpFBFPGaddJvUWdh#d$E`qxHUA6?rR;7d9CA&91|JuL^Fg#`hp={Jwa$uHo9wxmFNI zOHZxMZw{Tj?^lsGV=*2?c~X!On0?u}x=$cgk$0S5)F!V}C+`PU-nO& z9e;bl%O8vT&FW+a@wmJ$9?so*$QW_IS=|WN&F#SKyYt7-4l~0M_Z#76`F(gSKLlGp zK0`dutZszs=k{gehvORuJYt3;?l-~>a62%0k3MK3i~{9;Mz}#PFLd|XH#Z*gi5x1; zPAku9;_ZUHU*le<{qxErHonD3-mtD+9Mkr+=Qoa0xz`BSv9h^c?34N63h_+8#rq$` z^E3zE561fWPlpyO?yIOcUf4kLig_mmH$JdfXbu0)tMP!!JDaO>w`y#`h+9d7QE5LWfLtv&(ShzmB!pH_q(~!!+&v`8(H~cf|P3 z@pjCf>j+=kbac6}@ZO{yYm>K0mnZw#2W>Cnn$;*ct6!3n#icB`1Th&W>12sg;v8@rA(`1vU;O-TKWaHBfhc~4E5F9iw* z8{sB({ZO`DY}6*hosInvYZvw7j$90dO9tCW-VARSY+SPJxo!hxFxjz$TakA-F3V@( zrdBIN+=d$aA@6S3&$Ily(}VY(F5)J=rt2D2=Y@X$-3Qj*;;|~u%kx;?Z$NxDo!H zZDxni)K4Kg%74lEwT&N=d!QY61-MslIf$hnsh^R&ah<#uJifNK2 z4~kFUBknh=8_ApJ@!$l2JAXL)X)_#gzY%V9d2`P%3!i%jc`-kzT3btbAHRs6LAAI+Bd`P z%hvlku37hsh-+3ik~gEvlf6^lvGG~iuc1bHef+*+)-LAEKKiFJPzx0!c|&{P`Z{aJ zi`w4?1s<92DR;kyD1zr@jEAjZ$DWa8Y?d3|@N9pwE_zp4jqWTTP1IbEEcbjICph!9P0Sj#(NUN3O_ zvUms|S((=}9co)ANO#5lg0;88h4nX5oJIL}(?$8kx{)2CPvU!e8SeYLzh2Q_G@M|q zKNk61C!xG7|9=1Y+Iz+QW_2TZ>p3p7?^V%fEAm;bxNiRap$-6WS0En|aeS+5vqPTG z-`ITf+b`M;5pm7xMs~>YcwpncMb|!dh=`MX%v$`4=lQvPS)QDh-FcJwEeCH>W3j;U z+0yHNbc?)Zbt5|@b>q}W{x|+zGaPZh5w7P!l$YhR30;4gN$oAUv}Jic1S^NM4*tOX z^ZpX$F{>NN8{&Rr?f9PmPI$}=N8E3On}V4jleZ20d#(2+G4VXJI^l|WGNT)>AJ+Ac zOGO;ltlHu?`cQM69oAvTw?$mDI>=jfT_XcK$PSNw_4ZRDPU7s^@_M$uIjheyqL>oh!tz2XqF&N4J}LponW$H?l*X_s6V%yW_ouv(0eC{YJPU zejSI6&;H!+u8?@1S=|UX$@4lh{+>6+D#od`;<|V|u=l;*e)?5snBj=~jpWUPMOlBr z){Wj8I~kZ2VB*-`Qpf{a^2VaUB?zL}tzNn{J-N+7JZeO-8 zH>Q0T*6gHyMz{rC{Kmbf_mKjHgN<-g{Cl^|zMXaUO&;7bzr}R3Ra?q;pO5OMRoKW6Rt#`7!ZvD&WIa7B6i`{Hwc%)VXp_Wi`NeXHi*1h+4{ zQSOunJGT;f12@$;f74x;o^zc7b6H+*3;!-nk6a_}H>(@@Ew5|GJ8t>RLJ=ptv#H<2Q%d#d zD=05pUq5HoPxTbP(VH!|x2m`)-TjDnrKVNPhpL{W+emiMZ7Tg4)~$0Lc6yszNM3D+ zmR;v{@pxeCFo(I5&~M89jO6tkiuP>{aBprqtLD5eO5<=hzn@@wDv&2TcylfDTi|4z zZ?bvIYInY`$ZJ+7JBaPLz`w`Z4FKBspM`mB`LAhdZSm{kerE%Re$!Gnm!q23NM7+s zFUMu$lF*1_&Jy>V)s1k2I^1`jTXeV?j=0|lH_CC@g)G}=|6U-TXI3}DP3mxGwqH8h z3`g8=gzI@7*OghW+;PkPPf+~2-j$1AG0tK>%RCb^TD?MSH?}A0C-JtYvvUG6=_$hXG-a^RM`oaDykdEY7qJC>OgwD!o5kG#7r2 zyVPc1FVE}D#>q)vg0;CFB-@1`j+XFXf6)PUT+#if{Q%bme`>B5TV@AeckD0NfbZ-h zCSSoY^*^`8?;45m8{xR@I)nR^qFay2{!Z42+n|%T>HWE1i@44jziZT}lXvzPdrcE@ z<2B;id!T)p9o8*h+Ev8$Sp5EwXx|XWWq$kas@Gl>af=pl#q%6IpRsj~e(qf>#;M}* zVx97XD6e-V=ACWfgtce+ccIGpifnYWzAn z8>fCdWzq^W9C5!9Zjj@${5y1;MGRi*XN2qMhIU|a_T-90#XKPAw{|_NqFwNQh>iQE z?^{V)J~N{j*&z-yHfCGaj@S2G`y=&3Udet)3-A98>u{%@|Hv@HO}5Yu4IKAikoTq;p9~<}Obc=2+;0Z}?(tJs zK^jI+3C)gs!rd}?gSzi}&Z+Xe~F4dLGw}*f?tB&VN+2W06O!8^v$z;^y(${FT2wCZ1vC zbeJK$(FrMCd%Jhm>WcOjy|uRcX_MRztnaj~zVi)3!3=g7$(y;dIX{e>GKmdOq<%)Y zX`Q^!PMY+I6et`_xMJRE;(lZO#Vfs*vf*mkuP_$lrEH_FLb$q3r9X50`xk6MBUd;a zu1eyO-s9!gVMN^Eo;dzxxVN99y+F8`fi1($@pjDOVPN{>r6Ov8aWEZQO1LOXbPUT3&l4!xiY;YM4SC%t^U!>*I{yX%>n$El+Inz()0_^kWt{VUej zlM`yQuQm|llZ{h%`}*JKi@auaieIr^I5{rMzx{vs@i!62U1NV7(DlciF1a4&7bror zh4BzSqj?^1;*bkq-i^2!Tg&>*sP6l*&sX^#YuMuVV@3P9E<<_Q!0fQL=Y9+FvZ;~f zANfr@A;sGp8}Ibn$Nw|gA=yIv#tz1Qp5=!bOZNR(H`&h9emj9RyRu*7leM+C;3>`btvvSXTep{iTBsP=A;Q}mv#$o3c8%L?!OSob`l;`UrY~Ayr!11SwXEr@zZ9P>y&wB)Z zzwkKNF?QQ)ARbVHd<*lWb0M}j)^8p)cy2e5H+Zk&uOWM*cmpHcj}`1|G9h2uXz*}6#t&6s?rm~h4OLW6MJ$J+6y*Ifqh!I1kI z;f8I^k)S zDEp;bnT{vRj;BhI+kwTyE_?mB$@=;57?hXw^T)Mba6Iu*+4y>G@}^*7%_jckJCI)vcO%i?)=Y0+}OO@+M6?r`GJkAAG-6bXGB~r zQyZ?P8%HIl?eU?A>!|Vj$69O5R~-TH^A7JuMcn!t-;*BK*jWyzCbhxM7 z^Vm-!Ze*fq{uNIt)q}e46nCxiono!V??5}beOWv-+AF)v5i}OM#Xq1 zbZ2dL@ag3JYv;$IRhR#A_S*7fgyXX7PLBn4IHnv`(~9xhrQOma_Zt~lSJIy z$lBy>(8;^wnCTaYxWxsvwc`xOW$o?LHES#KS@Q1M>=1qn^A5vZ{bH^nuh+j(o4j$p zZp7B@U)*Lu#dU_%OSR=+*A}QJiwDmO>vgy%O`h2pgxe z@#OKlO*pK~2vBKQT${Y1F3s)uKP$saL|n7F(Rk9W``+U2Rlc_vzROhJs^iH9FWQ0K zZ-0E1?{C`8zb9N(r6jj6n-6W>u)1QtSqRsd*TJIXw_=s=Ml}wv4Y!f6SF`;4uTMKx zti#xwO!InG`#Sl2h>h3ZsPbK|;`-X;4c>-!VDs23w|(#+D5QQyahB2fZTQkkzj=q$ zmLH;nP)`;JCocMTCn;g!U?X|M*JIr84ae->@I6>X?q`VmWpkVzdWCBbIaFhLlOqt9 zwTp{B`L3c}G+a^Jx^jZsm$i-ed*5HNer6`WksVwop}Z_V9P-&)ATJ*2I#llZrnt_P z;_|Zj=FeNh#|?#_{f64wMP8TJ=T!OLSGvY|K-$wBzdsHBz2f>%{6*9JD`<$-D37zY zP`zkbx9_VSw2_TQev5Nl7H2z8nE%Q~Agb;%!p)}f`rGz!)-G$`A6oU~jcg=bF&-R) z(Y`Dmz8(MQog##%#&z1r3(fhV>BC`%Q~U<^m5X0do+ST%H*0UVK0jfhxW8#iZSkwk zLi@7$#nso=_YiT->SSN>xWJ*!?RfN&zcDjQ{fux^JkD4@^wIh|Ywm}{cnIj?;onCu zeNPm&SYte7M&k7vHbC8KdiX05*Q^e9sM^mLyl7w6&u?4hdsMkEYs(Mu=bG>D`{J-w ztIXsR_Z#^wqstEqQrjFWo@Z7!!VS%CzCPdno!=|&-?54-#)GRXwpVsNYth!boh9Pr z=hSH5Uz+>lcTfJJqCXDRxNh&A(`*OlU;dmZuUXy5zEN(6-2mXzNguOrS?Xtmo7Can zFyMl;6et{Qgq!1W#^zbubzQPJgQu7hW` z!+AIBH?P020N2UTV)?c$>xc4VF`uz`*rVqi-)+FWe&rY>)Oo@`y};Q8b?FSmOcNtFuOSKQ^f1m$J(*tdS$jSVBD zenz-?-j25hw0MVq^^*dHgN<;tgD`$sUcY{C-)Wl)*L5n|mrX3@9XF?Et+-p6F`hAYa` zz~g~6wCA5#{+hVotZwAD^t|Tr!?Tn69%Y6j?l;11)a8c*F1uz6@jSD-5w0JQn0*;w z_^-EqH^UM46RzmD)EM+j7dYXuzix!6EB|F{Y;T$u`!{CTc8No7qzsj5VgB`U+#><^ zxI3>tmvHkf#I=Voud{Zs{*P}CE4PAqjqEEPS>Sn{tv_5h?$!T_`_1Y`xb<9KmM3>S z;?!E^Syie19GAsf??-RWR6S@T8;#_Ra$Ghsp8QLvlQ#lUb(axtLWjH3@x*miPu|Ez z!WG*^U;*X_X5TyNdMp$n>@{AG4MGNEwq^a$$188y6XMqee`-;0%kFb@>At5nq2KUL z77wl@%FE^#-@4yCn#rpFc}CT?4inj;xxeW8+lWne-<6MF7u^ShTz=3y(O+vB1>W_2Swr1*G}EpWB{?yVxpo7umG^EZC}u7KNT`<*{ElTX}l zB(HV=%Ec~RtUK`IMdEp8bt7Dd2glV10zmGNch{TYi2IFjz5F{O%npz3*9P(=KeC1I z*NE{v$p-3Q?t7k1l*g=YB(F9W$0eNr;KllPYhL#h`CUWNzN`U1k3D;Q!`vtJ z1Kg_X5AJ_8_ZLeqshkfLnrfS0xOtobyf*2&vxZ9v3kMt7A<5T0S-*M9@pCK2lku-> zlh@AQ`^OCX%JwJJa^0z_eYNA!zR)de_w4KZ0gAF;;J>xW8_>14Cocb}Vt!FZQl(;K z-;~b2cT}-&u10wsr#0u_LkHbb-BwlPq)i}i)pP7R``%y0zJ)e5Uia6v#n~AI=o$xAL_rYEgq6OdB45=tcv>)&4f3yuZQOcc715d`)9&9O8C|IJVRKQ z&qi-Q+AE-%R*mfI*X5nP=Uv#_6i7J02sfhZH`Cv~Tuc8}HGZAPV}95YhUXm^P-|VUt-PL3*QH-wfPYo4k3QygMD%=hYhIt$Ips0LB^XHv?p)y5VDq;VKI^@|h-+2{J5Um8yH>P|^hj%V5cw0j?>-DZ zu(Cf+uBoj*PSrPGFI=(Rs?j2^S=}few2Pbji+!uagY*2_@>!C%H+Fq9Uz@yD{pR8A zjrr|}Dt^mblvj*j?Mz(PV{ta@;Mo=9N%!p9;=!S_?^7RCwzuFlrnpt@0Iv%u{Bz zo4ol)FwT5{`|N9P^&$Ie9?SMEv)hKsh0XGIn)Tj)Hf-mAL~Fbs+_M(j8=DUef2VRj zlz*Z&J9uwLJDdc#U(f9a|6>dCTDL>>IOF-3#o0xXbMAwp?3cN*w)Uo7f%3u)(Asr( zKDChK)edUe^^4T1=KQcv6~841)n;FRs9D|#kN$Ec$?LK%Z&myHb@m-p#lE4NYqM{T z_s0i-ec!%$)^d{9YhB(lKT{yI$h6Q74xJr3SFwZd^4i9~X}Dp9=2?Zivz0H1Dbud90@_uzZ%Aj~ zL#x;~^+;{@jp_2kJ~w>Xe7(@qvV7+3+k9Pm@zu^{qNeeQ*4l+Q{*8lm$iDrntivSC z?|T(RDb@3Q-oo%5M;*jM1B6;Ys+WZ!+$M>JHh2KM7 zp1q3X4O;IvMNvw1pU!VftN6`7$(r9p@CIEzyZDf#amfb?~23u$c|H~*Z zdp_&kgLgkyWKO(c?Rir%pGCLBJi7}3etr1m758m7&aj3n%Hx=T^0N8y=r8xWN!)K% zH?nUYMr1UOy5-2;ABs5n>9zHnj^nUBZ3lquZ(2D<#EmVi%??@w^EZ3`VnFucp(3tX z-OvsT&<-r=@Av4cllL|Q6800W7!Qehw8M^Y{Q6TXzt~dKd|-|`uy6fbf;MQ(+JnYN(a9syuJ7)J~x{kgVvYXt`2-nMTS$}-Q`Uv!*az7(n zXB6{xCx9DUx5aQdRAW1MIc{eFY=8Kw-8U6(klTT^N^*(w+H9M)FQ9ML>o@H_NQ_sEuDNs1r2sfmQGoPbF z|4oG(*TvZrBi?3@&q)1@f-n6CoA8JV#Z^Ho9B6l z&4*6h>b$qiaK!yaxLF>*EY6OcwD*zXd1iGZT;J>1Z@L)nub-?Vi$x!3**GdtEwfK#l4^=9EY>is^(+8-PKe<+|{NcbMO6~7BPc44x0=4+Q0c!D^2CBtx45`I; zU9J{CbA?*`;FW6eizC$H=bluHAAUwHzWoKY_$kHs4KJyczc52Bep6a4zE83I#og8R zzur!2@jZ&iKM}WD`9u4w#n0`d7T3(YMlk^_0w0(u|Rx5w-UbXnKN7drHA6JX- zd{QmG<7u_{_Gi`NN4`{xAO1=WKHW&>>eaQ>ew_y#SSs^pVm;LxOUGGQ22a7#e+HI? z)3MB)hGqOzEa`d#U0(%4H&r3MckY2(JiJrwJ|V1Jgb+p}k#yj!FuuyGz}u=2EkCpd9wxuGtF`$&=9r$4GvX{pS(&fe$xoW_(8S!fnjR#n;uq+ADyNaKQdh{zWWrl z`6qI!TKw!Jwf0FqpcX&>h+2HtX=?57|3t0)(ba14olR=-J)fwxfBjmu@;Cmf7QgVB zT71_UwfMnr)Z+VgRlB~?w7Xh-Pbanb+0JV5wWHLIZv*?QmEY%4i(h}3TKwn{YVi}t zs`YR1IJNToPgINF7*vbj;8csB8=w~7HBc>n{1vtROMZr0{OC+I_;mfNzAaw23bn(s z=)lswJ(kg*4=AmFjavM~mTK^+eFYNOPGVEBblrz#dxX6T3@pRX9aP#LKMU*bv$4$ZGSC<6#XeXDc}e{s zjeo*})W}cxnZauD8*fxQzO`SbMt<_I_bT*HXe5^2_2^goaIEM4z|_=C^24jeRJ7B9E%Y&pfUc-|>W6{9uDx{M3_b@wKPb;`^Ub zi=TW}Exy)C?f570yjuC4@2bVmtXGR4?4mY*ruI>bukEWAzdP3=qZZ%wvs(P{FKY4g`>UCMvFDBthkx{3HG|bIH*3#FGkHtT<6C?_n%)NzGr_0vbNXR5_9y)K2Ws)P`_$&2{H|)_ zKQ>+M`mkH^`;#5dtCc^xh1&S3_bB%7!D{gv4^fNnK1?lskEq?4gwfOD}72~g08=t{JYUS5LYVnhosl`t{t`=W=LM^_( zK`nmrNwxUCAJxXc_ZhYF*FUEgzcHm2-~FOm{P0<7{hK;R4L;3tY5sV*#rKcV`=gr9 zv^GDb`KHzP%MpGNCfa822dicNPVawn9cyj=PWI6(&aX*+kIDP-$o^y>tM5;v^?`bm z_nV3MlO*ML!xv1=>|e|K+35Xs9{9qf6@0S)T8r|NJp(51m%DMh{+b`waR|Tg9KL6< z_4fVYy^D2PVl2K_kje~f?*K< zPxrS(Z^h@FeYay77>@7Zj^BiJ??fzJxA6TpV`-0LnY#l zx{F%;$Zl%!v%9OsckZbcKjc!2AKXhVerj*E_*!SR_yxCGd~a8^_|cQp;^$6Qi|^{8 z7C-D$i=R0~4L*%;-P_>(_kp%pMjcqDw!_l9BbNE?v2=96vbYtN{%x^Lx5rW(-#SiH zBR}ger}jr{Opx#@k7Ja;@d~5#Sg%ZR4Sj(ZMa4)e(_qh_`d7Z z;ujR-d&j7iKk_fN^E=1BYVqq8zhA{ZSFQX_3)SKWw^KX+^&F@+K0Q~emEY}AE5GXy zwfLdK)#9h>)#7{4Qj1^TS1rCLpcX%Rj#~V}4r=iu=c&cdT&Na5*k3Ka|4y~|iAiel z>+eyE-*~TD{OtW|@ne^(!KeAP|7V;RH}Nw13)WL>v1}+}nO}!x=zmzoe#Fwpw>$aq z;`};rhZ^~5ejN#`#do}^7C-!{TKvEgwfMfAT72*OYVjMFsl|6Us>RRjs`mPLdUv(> z#l6(xd%LK`uXn4(ckizj->3Nb&B9Y^=3jLG9^Id2_5Mt{|IO27@hwXl?^@jT`1M6L-b=lyp*Ol&{q&Ux> z_k8L2%;d+be&03^+u8SRy~6kFTix?`+4pV3{QI^+*v{_HY+QwMP)Yvv9H%z_M7?V8 zgC9Oo)jm?S8DN->(%1N{;L*0`mI|0>?dmR zwQg$qcZ&bSQEKt?$Ed~69j_MOb)s7Q@JVX%(^sm+4-8j}pB$wY-+QfE{QPxl@k2MO z#ka@Q;wLAl#dn3&-d~-Is+GU6L@j>oJ+=6e57pv3d#YIM&XSBu}M*#6FQ)ynTUUoC#>Lbdo> zP%VCPfLeU-Ahr1Qm#D?}O;DTPB4;Wd-wsi0pW<6;@#F8R#czCH4L=M2-B^zc+lY7T>#CEq?w>wfLzY z)#5u(Qk#F=qZHpi-$SkZfm77t`%hDgZ{J!?{80XhZijitw*!_9J7O8}?NiD_pn{LsN_@v}qK;s>u%i|@KoEq+Sz z`e)!JwelBURg3T5Uh(*Io?7`sZ>Yu3_EVexL+7f+w_l(Zzu_Xa_=N##@#BNk;y0$% zwy)@=YUOucp%ysTMy!OD%q8fm;0Z8*1^JdZ?XW_}^43zwd3e`0;nt;^*I0 zi|@Hcaelj2Eq-paT71{_YVku+HTX1ttUr3+(mXN8OV6=b4<3i5`*7WzpZ&}6`sp$4ezx7Vv!;16_DX^OAi2-e}LYz!wL;!UELKDqm5OFT?rP0pDG~mwa80&oRSVypa5! zGbvuy+9m;CQIgMXkuP}*&Q}_*#QE6&K)=_4&$$A>cSHNl{O6u&O+UhO^g;dp1im+z zJ>Nll(ta~OuOwfT^Zf;U3z^wpZ{Gs{bCmR(l?<0>W8EM>VWS} z;7jF@kM^6{vq_RKcNY4u74W?UeD?R`_?)w>#Y=P#ydOL}3iY!A-%{X9b3WQ{re9E! zFLgHR*BbcV0Y1n3sGn87h$Nq@FY;{xeD4BZNRqF?BA@qVj2G7ov}YUO%L8BXW7LoK zo7por$D02(;PpfOj%(Mk^-ADt_(YDcNs=$j`Ht$@vGpq8OMNQGr@gju{n~N^Ig) zFX@ou%bW0#|Gby(U$Up?0lfbuJOk_YSFud;vObOV94|vNv98U+GQmsFY^-N_$?VU5 zWKYlen9l;&A5h|*8rN)xcZBc5KZ^R%emo2R_d+51&wh)w@gU(v&qaGqO=-4nz!!Q< zj?X2@S0KKeW;+7-!qepV>LvMt=W+cCnynuAB9F`Q`6c;s#OJ899SMBV>2iD_Nj~rS zTt82p?I_@jJt4;zmE=nipTEv_H1O3o$nnJk9ZT`8k7NDcVta61!1W8)+5QcD={|d4 zyX5Uff36oQVtYtf)X)7Rwm--9$Tw!u94)q$rsdB4SBa1IoAEhUTWf#0Hu$_#VG{C< zS~gF67Wj&nAs_8GGf z?KtqC?dMNn6Doy*lfLkFP%m{+HaPxJ-1rRXB+Sap?(iJTHDS5zRXNH zKA%Ot(8Z{qJ%;)PV7=!|;ET*gKH6`lUqq5G&-FV8`1$}}bdDTf+#;WSFzT1M9rZgG z`1%50(_G}E{bu?#O7dj}qyNqWzJ9>x%gFH+B>6m-Am91G2SZ6Mut1K_ew(%UBzq+} z-vz*T4)6tEm*aC;0b0F{y0KUXq za(sDNg1V8w`A@rE+{;Nj}#Q zva+BFj;~#7C&#q@3M$1@P7X2l;5fnSM=@e0i?lq=MZx4EUNP`Lqev;*;d} z4@G-Ua%^P_17G1oIsKfHd>P{NY-PI=_=?Nq_&gT*Txne2%{HR{?n`ZD8xDMdM&zUY zX8sFWK81fAtKU*6Ge2soNzQ(*9UzGD* zHD$II0X~nUeg%tsIVg{^EOLBHU~a`73L)Gx>RuADJjyB74zOZqQjF+NE@@0DCX$JVw{pkG>2zXnPD zQk?IqMYFZhpkKYD|NN5vb6v&t^K5O4fPRiojRF1QlJS|6)Gx#N?vHP68x8t7Kb4EmdP)5}Be;GY=V)U=zf@m2|79ih zOLD&ZQ(N1v1O2j+`h_I*bBsj&!d>QQQP3}Xo}7L~N&TXn@BZA@w(CK^$Y*l?OGxTh z;Cxs1oul0V`g!}v>6el0AA+OMo(~kZwv7S(a+3OGCH2d3zN-e$(QX9&5|a9PS6OTC z8~VQp*UzzyZ7k>)T`uRpyrh09&NqDI9PK91&nMYGgeCQJUBmVBY-5XpevOj)g)GiD zDSyT}Uu66oZ5-$qK1VJ-W0Lx5*P?z8`nR#&0Qz}8m-AmjQok_gyJpH9?Pky~B6&SE zEva9g^b2oeyAkxuOX}yIXstbv|NNuTo};JF(Z+**MalRKd}3{V!Z{1)fALRn{&y*? zhujSMHLXDZ(SEb}UszH<&vmHZ^)u#Zw}5_r$?=P3@p?GPpX7X(fqvsbKW|=6znDe+ zh%d^o_YVQSTYxVi$(OXqNAaRvi1viL&ZD=2JvGVkgh$ez1+L%apkEC1D@f{>meeme z2KCzk^t%o83rOl0v)CT&UmRY#UX}S2+rtC7wzk_rzv4=a7us*u9Ip-sh{U2S_M7>yQBuDs=NsAgHSI3YFE6Q|%c6eXZ!o|3S73Y&1N{=9Uv>@p zkM^7CXOCO6C-v{ao6(-5M!u#^0{t8Tx%jM?)Gx>R!l2(&(9iXioPPC^`gzB5{l>qh z-3|JMB=rkf)Gz-X`p>zN`iE_853u-bLj7pJng61a`nhgF{jQ$znl>5q%Sh^%kkl{E z`4aJMZ4ZKejgtB$Eb136pgn!7(4M=W*~yj!zWmo{Pug#0&#Xm0-|N^v#5x{W8mA3u zGgrG8?3v~BTiS2N=lIfE`y=`DG4$VVS9P*I0{YeeS5802x7OxkB)|Vwu9g7( zTzq~@`_1(8TGWs5Jh$=o*JZ9Y75ID?VSb_gW_+oLHG2|XlJgDkHdnh3_==KzS&Mx6 zo$&tTaE9yGZL!u7UM}N%1ofl+X8JX*wWeQc0P-alAm7#N7Hclx%T7l=+Hc0^e8L(Z z+0$`5@{Q;|SGynV*$|ZTUs5t&f)kK$c;C6&1Hc#PFUOaY*bG}i_=4y`tUv7|`e)g~A;w8`d zhOe2cO#{B@U^za&B%eRdu~7tPb20Y0DP^G9Jx{la|xbIh7~+H=6yFhtItNlCuo-RM7fR5bcL@TD%7 zwdr-ftyJfVOfUnrPb7?+7?ZvFUM=bJX?KmFv?TYzj%=nBp1Nd@b)Q|R?@#Vj> z=D!ViQ&7LrQ!?7Cz!$wzj;|=m7bd>x87&Qbv8&|x9N)|7m*;%f&&X&qfzLNZjxU{* zurrtL6CIlKN$cZ&^m04Sb2=a(rG%K2HMm8?z>(&0+Q&A;%Yx}d zxPBs^>jBO;Wxlou_*|pq_?#y86#3%BH+{ag82H@R$?S7wz?YZgi%9Zih;Q9| zZ3*zzkCC%y)}lQfZTb4(o;<&FTcEuQd`+B>_UqfR7b@cWATk#9BfR9pXwTu@7ic-) zON>SRXula>qa>dr$^F-Nf%YEo6(sozl6+ClH+=8{?S0_$&XCj3`x%bwdAL zKYfArA@FH4k&pJ9*|WYN$Cu~x&D~-A@)7X)Z;;~)N%G|$LI3Rme2u`@Aj#*MCa0hG zQRExDW`XuGv*(R+`XwawOL4w2>lSFA0AE0oFD1$6dJOg36YTjZ@WnH7`eh~g;+)R~ ze4hcIZ-E?NUXo9nhWd2^zU9DYze$cSBN;DY&bJrveGYsXwT7oU)S=$=NKo)=lD^MFT?r%1^TT7zFbz0&n?O4nU4B(2EJ9mmyy)Z zE6JDSd|iNVHSjrameVgF$>(?i_1g#dz5u?kBwtLDFUtAGOn+Vb68N%`d}&F(0_VGa z#_QS|;PWn#vuBe)O}A=e`B`Xuny1>-ouAdmy}A1N!fpHg9PE z1-_^xU(sTFCqD0!$ma&CZ-B2+k}oK!UyAeX3w+-KpC=|~&xjnYT)EAV{>d@)Hr z$8>A{Yj9w^WaeSK3?2D~Rsg>GTTwsSZx$~Zi~5BRlY zeltF8k~RGZFZ?vxb5h-Ywmk5KC(H3UE%L?pL;a%vL;XhCz<fn! z!1pWg`BHNJi%RmPINy!HR|LMKBws?3&-DW8cN6ff2R{D`a{6T@`Qn^!9Ps@Hd<~L( zc}YI)Mbz(R;QJl;0x!zxSCr%nbH4Gw_XqH$B>5a$$>p;==eq^?{s(-)m*n(wOY-?& zLVL!5?@!=MOY(Uw@)gd+{ynkfL8bnA@?8ho+Q35z;a5;U+HaO$Vv>BGmr=j5j~r;* z68N%`d`XLZ8^(KlymZC*H?$vNJQ#XUZanCg9Dh1qLH$Ndc|-dN_?jfgpN$sBpQK-u z^9`N;hW0b?xjvB7uOP`+;C#bpyrKO9d^t%z`_IMip5x5M`5T7cv0>pL#g)&rmKcGQpdo3+1?Bwy-PwC9*E3$@>X zFDc0vwaAy;9`#EtMEyn%Ua0*K`275SQ`&E)UsjSYo<{vfja;bx34ETr(VkZM@{)Yo zOwKocq4pQ>#U%N{7V`_qA11yj3pEYy_pYBTr(aBxFHd~a7ix9D*CfeTl(eUR7TPm1 zW1-dx_!9TX>F55%T7F4%!1#1zd3>&0sBHm!{(F&+_M63L+M+!P&oi6HOPfVn8{mt# z!~4N#zZqXnk}pYo9T#a^0$(5@r(amso^!Z~D-@YVDCv#jdZWHGoLZ4clJJ&t^|-%P)#B%g<#S6j1K z+Y|VllFzFpB>4(FUWT{HYMp@3^@N;$DM>!Z>*&9D$E>y&@Z}`=vKILQ7h`;;KSclS z2dT3&@Ohp@{b;|L|B8})1+L%zz}E%%@{)XxU#+zVl0Wzc+VcS5+XwiX_Qrfo`_1(8 zJzX6ufYu6L09Ij-MroJtgNqw?%uB z{N9CV&kU?DoeTOkO6u1rsb7lo9R&LA3;Ovw%lXf1qF+P(ekFSs>iBod>bKpf{q_FS z|LwaF{jT38{(TB;pzBrSzxX1wrw8=w3i^4Umh)f0L_hkTTX8hXmzsm6?=>v*yo}7n zx?>)e4ZQSbu-?ea=#5wp&&M)*EtaHf;qrsa?HAv+yiNz2l#z=#?ndrUu4d0LKmK5_ z=YC+%X7vs6W>LR}ftX*MjhL?w1^o^L{j}#$KiaS7^+H9w z|1)BuAH^r(CEvvOJPh~_0=|?aU(zH#iLW>a^~-;Z`i<%PrgjMMg;J;=?Kjh}Ns=%6 z7V3B1;5W5HfiL`m9G_OS)<4kuQQRF+zmd~tYUjdwPjO4+qy1+3Wgn2^3%-r|jhr!4 zI}iAR-Q@U+l6*PN7g;n@J0JKQN67KHAKbWpl+T*lcuILCWydnu1xv>^SbE!H8E%JV zvOSg|2bPKLung{iWxNBHnH{ktKTv#^n;v1p3*xmea4^L_d))`X2IKJ9w5h82Eycd{K*hk&iK6Qg@*KW0sw3`xfHGw=c#E z?MJKN|6VA>cxjT1mjc&s>M$K1BT< zUUr`CC(zHnznuRflKO=?Uu4ECZ3yU>=_#jQK+=DC&iBB&^K3tZerZYl;*$FLm!UmJ zE}NxY4*EHJ$>|r9)Gx#N9`1O)?HAC`ae$ovJRez$7wT_4AEADu*38m|f_@H3|0N~$ zOLD%4yPa=a3;Km5^=pvypQDlMw{Dhp1?ZQR^j}(1zbNN>sPFlJm2;!=odavE$s;mtVBc zP`|7C&enzlpIh>KXAw#L!kq8w!Lzjyz!#O|Yp}@YTyRKfJXrskyHp;t^e5Y`@RGO2 zdDtFkzu9=u|BAKuaYp(gU#Kne4WC}nzSsulN2_)#@zZ`YzASt+*P%a1_?yN{gqK;4 z{u@4{pnVB^^{eIh@+N!&{Xf-BY=QP1&vO^_?eO>JDv8%W4S6?Ld1_sM?eMWM4}5m7 zlDj2x+>r)fh@l?8CJA6Ap zYsGQ;{`m#_Q~THu8g}78|!$VpJ;HBfeC%;g_>kQlda30CyE#P^1*v|0X?@uiq zN9Dgpu;ZI?nts6J_h;k=KZadggL+jv#0wk6`FFMB^xN8w>&;-bc6?)K8s?+K<5*^= zV;OJ2vS~kD4|hF-b^o(i+7HF;z7*CQU&1o*6qb$`v8;a#OOk?W0~!SW$_3s?IZ9#(Sf6|o<9If$3a-SkHk{sb?kuWc{^Yk-Vw|Ec337m zVwu|sOKoQ?J-c8T+!f0rFWtLiJ+KFsu|2UQ-VN<&6>mqIsU$mRPs8<&cuy=dy|DD1 zjivouEDL8~>FSN8|4b~MXJMJ*>uikytS3&zvY{WAr0+lFKNk4M0{>Xx9}E0rfqyLU zj|Kj*z&{rF#{#umU@v}Z<~h86nf(#hbAs>QWV-=Ag3x$Au2-c~xWCXH*N5urT5DUv zOpoS=(e)c&_ah0Leye_*f2;EC@V+HGJ16oX@_H8Ib#_<7#dRmc$0M_Ia2-3p66Ga) z%>g@ga&6eYiT)saB?q8f#h;M>Ojt_n2J2sq9r6Cu#`kf*Ybxr+?A1djm!EGp6U#HB z+%9xH;ZnUM7vML{IlQz^5&s$G>e7Ck?MCpU=Yn!SW{yHXIs~~I`F6rJDqVf5uM;MO zH~>GEe&LVM9)!pI*j?vG@-yw%wzF$qs8D=u*lzHL=bh?y5)UUH(T|y5&|dG_mup9W zA3Zy59zRBfI1v39Sc`IX?lsPK6ZkQ|nfz!bSAolQMf&2p9^l8o82oM?*|(+fWfb=j zp*@IxjIBd^{oq`#)wA{QP3*^@z)$f-`cj?zsPXpb`W5ABKXIIG9Qd*R!t(Z5;JDig zdDZ@^wYWBFk8UB~lD!(P=~l`UX)agc&5P@N;K$(Daz9cWu>5t4E`OzjxFx;C(#VhY zqs#LL$whh9UqpNT;$E&D$*wCnH*I?~@}nmBSM*~OmuuVa$JuTMKSoa8JbsKB_%Ze# z=GEwWwAZemUR-wy_|f@#xgV*&sI?z5vX@zVbpFQuSif953j7$~On$5y_Yl9-9(})~ zTw5P_vu!;1F}{i0W8R>DG_sfTGi;ARKAt%EzZch?3Vw`@+dO`x_@MSHw#UdHXs_>m z%eAAykKUa(ZF|i9yF4F|9AciJabbafUy+V;ZMkP%5EjE-NqiooIG?}Yo(|X?<3e40 zIsS+CYCG{}+bs}ZO`9pcs2?G(dDNoS6HL(c&c-P3~+Oe$P=J$2{EqOxc z$51Qu<2Jp<+in9t7B-U~tMo&q29f@xyj?Lr_SE^2{Jf#{NX~107U#9Z)6zVVT~@Bo z2Dw}KhnQEht4t|X8kK>6A>r5@24;kfEah-|sR}=qUdTw1A7 z3;g}mWM7Jd?Syp`moT3(GMCYONX%c9C&(Xmp1)l6pKHfKd-U-4fK;@{%`wga<;Y&H zt+~A}@zf32w%J~p0k{sex$H%L3|@uto8{|;9p4{sn*i|@>{;G#H#jgav-!|s$S*X` z3G(em{-fmT0euM+~exgT>c)9N$xXQNLg7x|~sbksnBY%JVEvdEp=VQGjo8 zmGW0$Iohkf4*fXn)PZ$=@T2REaz9cWY%j!@Q&?Xx63obtgiGg9+|#;AY%7%Oec$KW z@!-ec?wD7}zBJFPbsfM+E-`<#v>yt*R34Y4uWXsv7wtjkQG8K*3;%`lj)(dVtm_Sa zbT33d{w?tZLXsb&ZMh!{9zRliki97GY2BpZBE0`BG|E$VG35Kqr@NQN z)s*iGE$p|A;>#$1`Hn1)6E;+YZ;@!ZD>{|rB0V;gaFeSSDys4X_1hG`@iyqkeA~&k ziIBg-AL9L%74fCG-)?DpEUqZG^9Fmi@DDM6`P!qs&V?c2i4gaN%@p@hVLhAjgzwdI zy_p~H)cKM8yul2Tp8w{N;QX*Y9aOQtNm%d{*`RTGfwi@W8Lv z<~pFgdcQN-HVNXZp?`UNZLV=n$zHm+5ABF@-Sou3y0am^8r$Lci{gv)+SK`r;ub7a z`n7aC;Sko%2)Csr*^B&`=!o_@z5PA5yTOm{rFeaa@`NfsR$XV(#g}I%l_{OHs9k^D^lmmN<;Ek3VF zJfgkayPzL^6YsIz1AYu_CO?YyBDp9}M7Bk_hJG}#F2M5YW@?XBuRnrwXdNK1E6Vk@ zdxdri_%U?|_S%C)q9g?1|V(SGRW@gv0twRh2vX)f0Z?Wfr81wW=YlOMgk z%Ex6b9ZxiNKD7FJ4=G+_S+bX|J!W~o{hn`yb{hCGxS9MI71k%nkJJw}?Sb)iYOg7_ z1o$yDu)IC0>W4(RXgopw$nbpcat^9Hm*v&JbA3WL{_=G~dv%{U#Woe}u;H->Be970l4ma+pC_sOJLnM_jCEWud4VG^Lk07{=ihgz zh%d$K(W1Q?_C~pSw7=JOKiDfe2;*y0&C`t53&n8`wMU=0E(iANrLz~=b3-6VuKQ*z zUKb@E(O&j0Xs^?H-D`UQ?3LZb@nvK$%8R6TNiL|+cs0r8%4Jt*XMnvjhv7Jf^q}#G z>hUW1(eYmSeW3Zr8<#t^+uG;(ZFFkL-L%vs=4ApLj^FL@#__5Am|DiM^}C zQN;Il(Dn_b;_FrvUo@Vm-v{H%H}PKEgAiYl!R7s9OY^-^d=W0`Eyh=l%eA<1h31F& z${m1tLUnvm+?L6u8&8DXXskamD z9=>_nqc|?4_@e&N$>(W(dnIfSgS~vmmB*JVdsSVR1E*5{a`1lWt>OypOt4pY6Whzk zk7C?!#{(_G#}Tw1O>vgz*GcJm7F`da^-fwZqxBY=uhV>w<_k0qrv8`u6>9(FCyIN@ zU)0|6d>nmuo4nQs?3LyAsu)iIfEWI$x~@QS1s^CM-?1ioApA=XHF(dF;=D?7(KyDx z4d#h&;eMth#J&3xjQh=Pua=IZ3&M4AF!3h&fxSx4{d!lUA3a^sURortodxlg7>xO= z!d{BUt0Wic9o!G)%D27G_6YdVwe0V?uY=;NiQ8*~6Tn_)>+D7L+^}DAyxM4Syh=PI zSAKSRdt~-{RA(=;XRUHYEZ#psJk&qZ^+%Tn{W$d2yw(@&pt6KU@u2o%oC&s_518Pvi`ZuO?@9S*^Bze%mFCZom2B#Kd@JHGuey$ zKygCxMfPxWxsF?UpKTi0tMQV*C$ExR6hHC((Oy%h=d}RXtC8EQB7cEmUihb~f7}pX z-{5>G&=cQZm+AO$-3c%s%3dwZhxmPbwcfvK^gN$9-)?C?t7&2Rx<<`$^*Fw-m(HjB6`flizbw9{ z>*9;zkIs`_H;G&9w~2@3%I;g<-kBfI)%#Iwcaq~Acfa!MQXBLW{-AiGyh`)ha6QIX zpLg!JJpuOegs>kXJz6@i^%y)qAm&xEJ=%{%xo#-twey(0_;XF9$L4B}qP>z_E`R$6 zYz<(q{ARKj`GMR@a&1`uItuMI%)U}PAM6#Y=kpF8Uo>A=eV-M{Me&v6a-G`i0o#*c zuciZ0F4gfx`j*)XD%o!^Ph{40EnRUt1 zTqxSh(GC50_QVHlPceI4x_R1TmFIp-s*s;jhoW4^wR_O^G|1(>?C%+`mh1(RWxhi{ zdX7Q4f=8{?E&@Nsk1UUSO*byw5*Alzyy`T_OXNQ)jmCwdA6wc#=H`|6U&P=d-^PBv zV&0*C-K3-v^)vayP_C(cS8DyiUf!d4e2MRIgR{KwkK(HYvI+mA@q}xBd7LnNJ*%@9 z*>eN6kkskUyvABjj zVU+Kyj&lIt`8vu~JeJFK*F(1FK`!4A%&V&9B7Mos)E>znK`xgowo)4aai4tT@0oW{ z+{eEtj}vx(&Uw1~bLjpZ(nofDAF=q{3Gt9z*%QjIi!ys%tg{!{vsStMeXNb|iHGt% z-CtNZ9^-3m*FkmXgT3O5@%}>6Bg*g764wh``o6TPaSukIbGW()Un`a*-d&9)5mb+Wp-I)m;Gg@@D^@`!QRZS7U3++slUdYvCUhU*yMB zcb>myuG9vDAMIYezOCAi6t|=fBRNI5j*`yTLSBa$@Lgt?pA0|vbXB_c1!bw z^Q7|rYlEL#_(#cJFwV(LMSG-x+Ppf78Wfb>fz9+e8 zeIk4sw#Vy74XW!8ai8G%p5l?#U244##%Nqf>sMrE%3tJ9M)SUoFjF z=>y8w*EjfC@{gtrwl6wOv{&&s9Iw6^TBThM_6lq!dyyYVF3J<6ck*y5baIj0q>pTS%vl^y5Rd3bJGa*mSYo;Y{AfRR)5g6~KSbjJ z(wpR>>yO3W=*RgV4XPW=@+!aHL3&VsvALeZr##SjD#~@&lvUa=uvd`Vt0KNYF)#d6 zI{t!wi0(IW_d&UC{%TO&C19`cuQ;BlW-t9ZW=pTvk{`&AEzMu(@bbA+VSBHugiR?Nz1U#`^)d-a#JsF8gXN%<}4EfA2Vl;>&v)=KFD54z9Zt z>=oEd_Np?kEqOHET^Q$py{^>Rt0Imh*L|ZF$2r79`HRLA>Ao0WIp=EaDv&Ge#k@+# zQ$MD9Jx7dte?OG#wtWWI4FNyemu%X&H_G>7o)GQT#N~R|y;{2(?3LY2_98z}x*&Ve zb>wIO?KSa;!F88|y@Gc!Km!kzBFCb;BUO67&C_@dU+vuu$#~7swUX$whK+u)Acx9qVuH zc|PJ1^J;Vwj&nZDuGS*p$HxCh-Ic&OQJ(J^W|8$;7cW+8+q52Rt8KT{YHVwpYL%$4 z#(TBarXCQGW91Bp8V_Kxx~^3rc*c`>$CG$xt;&kBEFKW=)B_grSUlKpDF1izeovhF z$oxrmGLzQdZ=Ecg%sk)oyx)6$-%Ji=zY3iZFI>NY(5f| zKKgO0PP6O3l&{S5g`k$@KfAa>&zA>R=9SI%ujc$0#@&3n@T(oe)d^%@vF9r5zp5vg z$L(o4UEN4G`(++sT*-6Ie=oJ4F9y0I+KKqI*Rph=QTnBLo{javO zS;zL}!_`T|7y4fqhcS;HLVXSRFT4F5+213-M?Dn!1+Vkn*&EV+O?&Tjz_Auef3V#oN@%g^iX;!$b_(DCD61Zlp9Ij3#9nqI7q@$C4 zIq-#bzNQh(*AcBT?GfTDKALp|Up->|vE1u?&_UJ_eDw%iGkS-sQ;09`Q=CsY%~!#C zo8}exY6&r4Lu+o)9wok%G4Ajs??Z-;n2(;3jBECQ5o%bsFOh$NFYsM%yO-;2-~wMs zf$O-|TeQcBuY^l{!7p0bSM&_#Yu2C<>Qv$j{R!}e&zHMDVdW>FWA`Y=)mU?@wt)Dm z9&5HQr*uR;1HKR+!ADn+aow=b2z46q)ls4RUbe5g(Tr#bUn_zFsVIpx1(KVdhI zj(ua!L!g7*Blv<}^^ak`j_kZudz|=6N_^S1d#m^;`w8T$7BwUm&Sbv4JKm-}L40`*x3z!&(;+f9ji zbh60439bWN;6o99^^e1D)1D;0YR9qv+N|y%fIj*`zM98drWeo={wpKw{(w;<)bok2 zt|gpLU>x3Iyq{R_=NR*^)X?Jg8C%)CtfO5&(IM$yCb|^p2tE?RuU<2Ggn9w-m7L9e zCbxBjpTM}oV|hNNI&agSBKvAvT$%e}`l@4>m|x9J=6PIh9qUdppI_(eX#-#2Gk@I@ z{X}5r;^qae106ALUo-3IiH=Y&B>PgHudKg^|EeC(xb_=(yY>w66%zgnwaRP zq2BfvS?3q)ComsVLdW2g@A--t_yV7O)iGXV-vrkIF7S~SIvzOecI{c>D^($X-`DvF z-a@CE=L`Pb?h*MH>Y>0@ysj`}!3gzY(y?hS-xmOWoyu2nUW^Cx5#tU`gkQZ~OOcM< z74oaFujF6NdZapU*V+xZfE(i}wZ9rF(tqJP;Hy@`%5g^SB)DuOiRE zbICd;vyN8|yhD4A_-bwz^`o%wYD1o5>=&lXoaaEt;Av(Zb-pe&@FnwEs*c@7=Bv04 za6#7w!PmjV?$G{Ce0k2TY`%*1w4Q0KW8%#b>I~wmzKio!jKi&UKD&Ok`fq0a^Yg;y z3)nsK)wVG6HFnhqbtdtZx{UKx@a0y14?lr%*H49Cy+eDR?910#nS2#?-*mcJk5uO! z+6x9;z@3+;#Jn(4q+i8#@;aWu{g1%;%-74^A1c#m-M!&3ch=qI{)CLHde*+V`?Z#4 zKUB^mTrFkBWz`2jzYluIxFQ!YU$51Dq?}K^na|()cG38`D(dzw2DJpijOgYYgyCB$}GZFdsKOKw8EuG&ry zI<8Uf@U^A5-6e3HPq=0iu27lzDmHG*e1&E)Ul$Or%LrG>C0z3N*2uV`EsX0z!u3zW zRd;lG?W@@5M%j(q!F~AtefXVn9c8{6W;0*!#XnXqC%&3p;%iHOwF9`4A1hZ7t`3)Q zZON|&FJr!zb$qO}5-!is^4ga_TX>)0mi%hRgIo_q$nLKsTwN~VlKrY(yRSXX!F6|< zM93#%_ppu^6JJ*mUk#1r)zM>-AEIu+d`7;CK4na-chu1LEVfYJBqI7um8yr53D(0i zo%tF&@J{VT>Q6+*b6*a9g9fqQBCo?JWnPD|YhMY6`d`oye6*a$e0hi6sVyYF8YVDb zZtI9T4dbrAoN;-)A$2y{SM>{(snhK082`JuzQcU7dxVaPbbg($%M5&h&;0dDtRH)d zT<61epd-fJa|P>|>bz6yAp7d6P#+Wd1o|d*|6*M2Lqh65i7(W(7zg~H(|r@@82g9W zPISIrGVldH`>Lb&f#RMUh3n+_qIGKQFZ5r{d|h#JNWGl+@($v<1AHOwmwTTmbilZw zV{|I}`^Z&{YwW=J+9Kl1JCXet#!+YF>#qC2VcHJF(1%j+&@=C_FZd6FU zg7|7!YUT_1h+EI~0Uv=j#^oJ0UwfJOY7=}_z~AR2h5fX&GOk+6Ct8WG=6_aZ-%wxu zeTSG|J!hEbG3>U~W1!1?UsGRk;ky1Z;llZFgulnQGr~`#I_GPzkbU`=RBYWUcOMwW z9lnO`%aaVLSCV}tE0j;b-}}yDJL$NAap`<5Ht+>L!E>qW+tDKZJ+1>>(KF5VtMk=n z;0t{A6_;{G;kq$@KJfzAfnP-&>YB%V9Z?h4I*G4t;lD5rr{a*j9}{s1`9$bC#?`(s zq+UgQA)mlF5XYR(CuF|5Zxehq#33Kv`az>r}!2Az1U;h+2;9D?B}-hKAErJje@V0A@yqF%lj(l z6HfDmJOy}R_vlYFKgR2iJ0(BwcRziPRQS-J6%eI<~o_queiqzt0Re+po^oQUhNypQXm3Y>{yY z*OBeMI?8-qHDIKAE%D`ht-N+0l-65d7gqird2~~Zaa9kzOM8|0icMy}igCDAcR)w@ zf%F{4bj=KEzc6_# z^R@L=cWJK^U*YR{zc1{|#r>GMJR0Lp-ORW={*mfjvai&OmFdfYFYG7JiukzI(z~=b zh_ApD^L%uB|Gii8t2$p%17F}XZ$BmW<*Jtymq+6|;0yNCJePIci~RjE;tT&FK7Q}N z6x00*cKarBJ^}xQ>-vQM`oplhwdI5>E_8I;e*qWx^N9I4XZT3Xv*u4A`9kxrK9xx=ty9PQ$28DY+ka9+Dd z(lO^(G49CiJRegv_h@O|?nVD+GrM;M3; zUaj|NZxLVNKl3^=#)12M%Kf|!t2`QglgI+LulBhk)fliH z&Ar;+}E=Mzrz1sz}~h})>Qz4tP%OK55PU$h?} z?>>c$#Xbcq`vPB?uXsQCd-W@nYY3Mw;0`YIJxn^%d_*5p8Owc>wgr2tcj)`Jy_`=V zo}zzN?)5Y||B~%1dOzFOrDR`oh%f)KW#&uVM+RPS#CY+$j4QOBb(}%C<`S-$OSrbg zS1`eR%_3a$2v_{L^77SuLg95v_(c<627jLrar>s_d#dxvz7k2UA7NkcGv)U8a-T`o zG5f8Uk1Z>d>xi$Wqf#AI?)|mRyqdH=6oV_<1cc3-t3e6t5@wn_VonE$KdV!cg!1oecO1yXq`pB4R(xU z(Bget^7l;-vyPV$UpEt99VeBSudc?zI%2%QFWY^hKkN8U!WAQ2;gj9LwWWRAEsro? z?^Ul=ag5PbCG)N^W3rv;AYy2JA*qCho>o{ZnNcASFhp;YM zs2*~1T~y{PGKl%=Os`VzCBAyf%$JqFFX&edeEIGYd@UHM-b{R9UDRp5WL)qQxNdEn zaozCZNHs>dvaj>HmD_$o)-k+0>-cVVm2yAn7#m++yD#=W9lL$GwA61w+_igzU&Za3q+?)0d37xI{vp_X{V1vbMSR_A;0t`_^(nD0 zmoBpZh3m+CRX@XgJxF{#NPNXz;>#+(hoA5X9S_)MlzJQS6@P>M1jd1Qq3@qC`g^Co zPa1WH_gUsE?fpb~i1<<_x?^7$FYE;N1wLw@WL($mI!e8r_-Z?z>yAqM)w<)jpYsse z*TckDQSb-a$Hs|4aO8$8&67?}k26 z9wi;CCzaRkt#m9{ry2S=ZO=2V^B3%;KBD&vQ=CT!2XejbR6i%M^)B-B6mq7}JcjM0 zWg+9zb-dG{BXrK&O^N=#r$~Q~>&X5-`)|heX8053G14(uW*v*YZ!U++pkw_DjBCWn zqtyAtS9}iZh;cZjqg>a@e5C}ghsl2}Aik0=@l~)7VBpI)o&D4@j?Ijtk?1M^DOvFAm`^$6*hBpqufm)Cz4yAGpMWoKV)YOFJH zNaoAa!F;9TpD2$LUx9Ra`x91t$@Yc#D39ASWt4gs*;oBbTz9~}pua2oSLtHN3j;4P zUyqV~Jwbe>T(U2#ys);}Y$rNjcN_SU`7CuGOg3nae|g@e7r2gWUy()3*RqaJlqZR= z<|$>Kk0q|BVLwyiWyY15JxaZY_)1^F>yH?RThG0d`SJ_D`fmCYoWHlGef~1#OT%-J5~o+@IY_97lEQzDoi|FomvmH?as3D#F>l$TTxPp3b{!e@Huwmo7}pJtjZ*I?z7oQ|DqU{}n>jCBKzuz*e090Rmz=Nm zwcdu^1AI=sISeie2fTgvv8BuMR~V`OT1 z{e7|P?y&pBc(WclUkL+W;4`mJiFIwL$opY%9htALSDCNn-qp%;#8=uSz7R(+Zs0JQz5fe3$U1_rhBuh6bkl0(dE%=(Q{K33#aF@nOD`fP@_eio ze&VFv&ru&HzJkj+&jDZfywlH9fZc@wzSS!lKL0`Zk`$-d+~2mVW$E&H!!%38`- zvvat9RD#lTt4j1=8H;^Pu&4Y{TnD(IQ+f&Wb>lwgsE?42NulFrafnXjqaUaCPslo^ z(v0i%@M`5n($RZfdHsadJ{YU{7(Rz}Y);C>)7%Z^YvQGYGonm*p%SsPn2t4 zhn0?UUI<)m@ALf%p0^p7vcrAayQE`E(lPK5@9)=j96){#cAt8sxPAYYdQ18uFU(G2 z`w9yG7!=nF=_3gkr%-53WYNdm8Oq5y2V)uVR$AI7~F7|a~uDnlsk96!f z&paPHdJF5=@L+K|rmWt#xsJI>k)AL4d(!bSgO1QSKZ8p2_vy98;l_2q7vf{&UDk1F ze6{it=~(?>dFP{*js^Ow%$K;&EIgla9kTd7?S0ZQJe_r{bR3G-@cx{)lB<nxvoG?Gu}=>$txM{u;=GFwG7S2 zrlpm6Zj{|Tr{f-H?B4Etj16@L7woG;+Bc%>_#cCg&^bT-ON>KNksswhZ}9@xfqiw| z#pCwB&;H)ia*p~q&BsiI@*LoT9vR@O|6F;6=411nmCe8Wt9U<&_haVk?6&*04@k$v zmpmWAuV47pouqwfK`BqMkV&zsJLG)|u&?mlX8YB3e8Qk3bk1L|MEmkQQQSHou7fy) zevYz|`8u@b0qsNLD}6ra6X45kKgWt!nJ+yKid)O`RFv`}A2&<+P!aEy^TLL1=4+An zbET8)KK3}<7v=@>H@zM*-aq8XeE~!obnFng4r_ft`-pV(AHjV9r*(vVfJ)ds>@EEP z^R+YO6Hk%d*S%Spd_vYSyNYqW;s0D&qU$(}pFiQWj<65#1zhNhw0*+3c3k>^_A%+$ za)Eh1h79%gLed}gwztSQV>KTO_f4v)Z^APZc#AzY-)r`J#eQx}?*m_`(^9LMuXNMr zN*C#vb!k4zbw>^tQI-CJ*wt{pFO=7#pd<5Tp?fa%Io<}MBRm5%R5f%R4 zlRQU#n&zYbcLCK? zqaXOMJl-T3Ik}I|5Vs>e%vbBebJS-^$7T^9!7uEy-0NwwpRmi9?-;XPmPtkh z{tJ3Eead`gUU^FErukU?s)c>I;lB(z_6S_9%g<3$q+^FmI>J7{H~4}cEuS%8p6<_; z*JwVbe#Cj9+x{MYA~eoyC%TTS3_3z*jHlFnkFke~>-*w5z=io%FY<|9C|_;Yb$s8# zz6hX?ew^}Oz|}3yD_zIe4LU;SzVhWgsqp>e`SXbvxDN81+H-k5HnE27>-E~FwNFUL z`rmVW1iyCkoMP*3yZ$S5zu7M3@%Q!j9AETdDXPlJSW!;haUbfh5xD^tv*NdvEdx9)7;394lx3u2 z@F{n6gnhss?b>}(+J}zw+C9R)k`I{Ym4|fvw?RkfoWEX)`Km{(TjoD+@dDQYF3h(& z;lHB0exWQU9g{-G&FqWL>!TkB{e8~vp@;7qw)@P`XS7dgJ|-)i=ivEr9UBe~hWzzsSdJ0%+_r)fL$%x2m^sUW^;KU|((DvVDaHk5*qG`|5JZzF@b& zMLOnKft`4>A`XSVP}1Zl!t*P*-eIUaQr|JIA+677pObw>BbFB@69UW!9a=3_uo~sVb;b{>5o=i^ZEZ`@w4{#v;eHOh5@v+$NJF)T; zvcCsk@Ds6KwyzOGMym_SzHmP>>C;%i^m6&kGKyY%niE50}T zi6-Iibw9DBfS<^(yVKu|`GnQ{$M|uy!X^6&yY*1@gXVe#*SC9w-6Jk{iG0GleMOT;0o=X&9D zr5^3_Rog4_>ryYgh4;h00=t;c@2THgeS)4p5xt$`kg~J+@1^EBp(4Lu0oMU8_|4!( z_Fvb{`9gU|&%cCUb=&Uk`U&r`j`@k4_r&?*12~`Xbbq0|OMKPGD^qts$BZ;?9oKsX zT)>?-*Ana6K#~1uTnBLo_w&WJVZPdXzfj&MT)3YP???XT%Kd!gEKmwq35 zL%156xNibn$ivHBr(wL%13Kcm>1yWd%6)p24+vM}Kb6V9`Z^!eOLxiDDOt(yVZ3&a z#8+-UhEL-8?%kI8%FOLiJ|w=<|Id8%(Zvym?Bb9=4;_K4;k|uwJj{8qM_EC*n*PT2 z^}pg*yAEO zRa{5*tJxhGSNotf$|}MIzl!(6&$#7R(Ff?+k#U_lc#ZN2;R>G4b`M-`)wMak$lv4p zGQ)TCbLM9pbbvaKo->cr+ z7e43o^O@kkx(eX>)PPIIU24AST~yqD09*%lpL~<~>RHNh+c$KL@)_ak{*dD%-VeTY zyB}bvJBsapS?MU(wZMhzcGR%l$A+&_z93xDj~Ewp%-7ozF1z)%)pHeb-3Ec{s>y4V z9>Ntl<9{m-!Tx<8nCA=r-R=?d5$A8&N%;Hd8f6Xf)h6cSW^vo${Y;pT-jB@V_7JWw z4Y+_i&qIlEC|cxv#C2fz$nP`9ia0cXjq(-YLL9>Tjq`DcgY&Vk`6_s8d)&-3{=L*= zPt4p0fqmipi7MtR^GZtliuz2ouUX{xZrRrp=5gz|zBb?j?mQ1A+E;gx>!P?0;x_8E zOda!ebWOYV4dJT3l>2gczf*NuL4Qy7i##X18{-<**siT5TuBL+Q+W=?3q8OWaMkWE z_-bv}dI?wEOfz3j;i@~tyxu0`iVIwaceZO;!sVIe4lei~E53X`V7`v6c}`nLxVl`z zCC6>>1-nlRT!%M4r>!Sk4YSRB!4AsZpD4KALFA!No*2Y@jcR*N+d#N75-ww&Q_gh- ztfN3j#7FpnI)Q8d?fF<+a-Z90LEew^w9*o{LO$sc39c8`cdIDhjVtYhZ# z=e2K%uTX{KQ2Hq;4iT>JjJRZ8N{mCwBgNGn;0N;&el_%C=4(jj^V%lD75%5MFM-P` zzq+M3q<9!tW6cYivK#GFxZE9F7%%Kn<|`_29ozVVrV_4}>Ega7hxvkElyRXC(C`!H z>xkADw0?xEzDexA7q}2F^!m}sJ^=WFzwZ#Z4)1(H(+F4m3bT$FSGoPY>{oNRh`f#z z&qwc%m@m)HFKShUOKCOZf*q85Ux)l0B=~#G&)5$c*8x|&sP!jY)mI8!|KYwX^w*C* z`uT75_o?U1eox2Sm;Zuy6|OsQ{@_oUuguVe+E&C@-RqUDJ8GXdk6Xtzz<>+5^IVkZ z@9T>6_qdKcAA9y@zK&~Ms8tiL+BUW?yx*z$SkT`S30O}_U&+s_J$3XxY8R~|hq{Dc z{Q>teF>mDOe|4*7{$zKKGkycAOHdi=qH^|QkOzxw;PI0I@&ik2K?li~sQgw{& zWVUN79&sJmSMUY%b#=Z58u$XA`SX>SPc#&nPvAQ6Ux<(KU$Bmior|;`377X;o{xAx z;#j%!d#kt&zv}xX;~G};vbGc9YLjp|6^Afh=mEZfE4-h;)%dcuGvVrX376c*gndCL z|GtdtfGb|sb|G9nb1LIk?fS3oA-ul<{Fmzp|Aq6Xg?(j)zM}0)e05aVeLa%=_fh_U;8tznyy#0-3V7! z!i7A^>3!~)j~?myh@R{|YMSCuP{g5n@w~pi>XDHzLt7VXdl0VFIoy{km)%?OCC4Gy7p_|^ zaP7Q(r}jg_6};|$)87YPGW$K~VD|`rkMnm3`^s#$MEeo(<$0sBeWutV^SE_fKQ`b3 z?mQ1A`ukv!{vOwn?LKu7+x-cROEeGRN(%eJ`!R3I-Cwox_sCa!yo~GQ)+O3c2v^5w zo{zwVc~kCu73YN>n2$|^%=wBZJX&2u_ov0g^U^lEPpCv4y+uB^0N0Uq^!$$bI zhyP`>KgK*S^%&XLo3m?t&MvORgXO^mJUAjgV%$mLCo-46s_jko6&Y%=AJh5$U%C4z zFz&$b+3r0Zqt#BbuWW^$LkYW&zGBux=W8DWU*Howm)d7)D>825I>6QRkQtZG*AfF? z;Ipr|YK#279b5--2>w3qV;zs`d{rAve0AN({tM%%l)rBt#{O%}^3iG+@rCEqU>r`x zN2@plzP!gUuET0x)9Q&YJQu@hzMuo_1oj0!5{Iykb>#0~CBAyZesZ_{y=-6AhcT`p zov&#>C%&>lckB!O1@L9p-^U*|&tsg|?osB;`xoZRU-P=QFYy)lhdX>>9T?+59KyJL ze`Z{sx-sf&WM6?3D)`)C!+KiiaK?3P(v>F;qJ*cbBX=n>4<(AL+rUl3pQ;`t`U`bg&U}==XEDbY8BO&Qzs=>bUBXX<4jQ8_BfgTm@p>Bg zLcAzeNXoj88cr-yD#Vddn;VfvG#b@v3bB)^?kzC^dB=W zyEy*SLDex%Gb1y&;K#U z`9k;o4xsuD`|s`EhY$NeJOM5|@6mtHuXFkI>+!dgJqcH2TaJ%i=kW9K;b;2#yhke? zt@8WGMy?-wM4sdM!B{mz_ErC>;7j=X;40=@#^smxd1Bo1(FzylIo^*v8agF+W*x77 zagFi~@f8y~R=m%265~3uF|GZM>^>pcJ;v47xNY?uI(a_k`4T#%M1DVapRwwHNXOs@ z>?hpj%Wi(}`NZ7UfPL6K%KoeCWY%$5XIlF`=~#V7dHt7_j<64m$1Yzzk2%8^>JI1; z7jekby+&C}^D%XM1^aSDUh01Ko6%EP$J7pQYJVUdld_ISi03^@&o_xkeIn=~AFXsO zPOTHnndM_D?R2w-X|dZS7h5Sm35>e@>S?)d~Sg;U$x4s^7bfRSk<){FW!&&i2T0i zbk_0M&NsC`k&Y=zN4s^0)qLDiJ=F4d#x-UBSoLGlu|CTERp@9JSFwD-Pe3QH$S1De z^-E6oo>z6u=!|6slXHE(G?(y?Q{c|O|Z%SuP9br|^jZh`Bn1!L6}`g|1q9O!7* zPgv=QItzAhH~&(;G{;q(*X|MiK6W|hIrR&;eq1{B4D~?bt9ByWeOHA4j(H>3X$fil z&&|5RI;HU~?ayRi;kenp?CNM`Uj^%0s^|0l9D!@*!m;W~;tTy8 z*cbd?xu2(?Y@Sc#@eoq>5y^iXQX5O3buRj>y*Ej^FsIu=;0Oq%eU-HMWy)|oNcks z%8fjlOaafK^#74{998?Sb|mSD=TM@LY3%11=VP(`98aLIjxt}+5qVDN9L5zod7Sz= z>4@*kgpSDH%Do=|_JP>~KhgA#c|Pbm_A}@Ro$i`#YsuTO% z_rKy@?I_YQdN0Sv&FVBdpO1d9jx3$t_OHMNonj)-xqSFI^$XH5BIcvpxZuC?>$MZu zzII&qrJ|9J%1X`)!7u!bejol2LmaA;>SZg!tnxzH?(O>fwobEMTH)E!zxV8Cz7Gt1 zVLw3IW8BYK5`A0QSI?tsc|SmQk+b^&pabyR<;(BT`Xl&4e>M0f?;F~2>#vk5vacq| zzPut&k>g`(XkmYe@#AP^Uou~aL$H(jX14pxcL+rTj}w!yS#qYYJFRd+c{k1x6ucvoyxcl>wHfeMmpmDH1Lbhm%9%j`+M+( zb-uX3)joHe`X%Xzbw2Qmdfk@Ow7laz%``xeeD?15%)hrN2lha93Np{z~w!k z`MPSsIQ46NK8kfd=;#zK=m7rUC%hv#zv>dW?rHf-*_w1rm03rtb*qB*W$>$^3z#o| z=lfcKbi{p`PV2ZOKM|Y7_bbd?I8ObBbi{fZbi}xvUQd&CtiF$N-4p#v*@kqi`^4;5 zVFz+vSZv?KN=GZc;J=g$S;u2*GTO1EWBeanKSD>R{8vQk2Vp(}SL{m0HMB9K9Y?ru zU#8QzveJG#=;#xD-@3_+E4F%^+N=9}QP;x0;*S^Jhiuu`!o(LxtNdQ}tH=v+-R_Bu zYu?&%YL;-dtgKAm*KVDb*u6Y`Oo>*-F0PiP?2qO1+Wj4M8phoaVI4h9&FVVRF?mvD z_hUBwz^sRkYrO#%aOZg_u}|J`hWS2;{CT7oxDNaT;&$p1=4-}?W_5!;AH{tEc)wF| zyI_8A$P1e;Wn5#YG^-m4m+vX=`vR9!eih>deehqY&)9z3E@oWHWzFihgexQb1aKiw z()(WnXguf_+U<`)QdxVajWV5=7aMg~l z%sv?S``C}9`AE2woxaBf+|a+&{zSUSJ^-!*`$AnCn8iA_FKkv-!iBmP?>FXO#{R0^ zI&Dkyv0LDpvbt-{qnZ3oxPoF{ZI<7671wtwH7~?>-ITU9YDC+D&$w~=3l;_nEf8?*6tDh z9_RO8#(a4~=c?7jSL)=-=3m{?xOH4x8*l-4o`(|iuUNJ?`@?l)fA713`D&kXuDT83 zg1^W6jef!ne~-K{EpS~i>s)nP!qqM89=M$Hs~9iz0AHCs*?wy;XTDPN&Q-S~T)tJD z=Kz;+-QCDn(B}H1?C+6J;JV>|GOp|IJXhVGa76{KO0CzT|K)9CT=!l++SWDt>$gPe3hIA`u7c2 zGp?onuazB0$F4H#XxWdF{0#VlU+oaM{GI>NP9nbI5?^-xsuf>2uk2UBSMVC<>xHJT zm0IEp`4{$eU_Nh_e@T5voL@d#@l|j>lHG%^tiUy-<^%0y;!AnJY+o2xU-Nq_zO3R9 z_KCJ#%Y3b!`n58U_=<>p6?}F4h4&-Kd^I0k+&%@X{a*!f8T>^39L9BQ>jzpB@rC;W z%GLL^;tTcx-QickS4!aOo&B}4Bk`3kGhgWw3-h|A{(aM2=4)u@2ihsb7w!viny-T2 zH>Z;)_Sg3aTx;ijt?Wd6HGF1{Lw4<}+hX5bLBDFSua>CbtMNnaRN|}dVaDY&UrHgr zN^~J^w~b?5$@tgG&cs)X#24&So{z<@57oU=IM2sOMBA-AWU3UZX6{z`0`y25Ude9xd z@(KTq%-4~PA8Dr(Unz+%r}7Co&%u05uQ1z*&etFVU*I!uHzoEb8ob4=58*m8U*VgW zuj5-k(*90-bv$IYFS~qM?Pn?&hlqs0%HQUmr{H^r>$Lu-u2t%Yuf&%ehcFJr3#a!X z%Y4<|%zPbN^RX5rzVN(9#7C$2!g*mQzy&|yi!rX_8b8+lLAX2*n{~A7SFLoE^HtbA zbc$ThxT2HSD!Y@8)nBoWm5xKrw=k~8){nI_h_A3qe97MrV>b@fcbokS?4#6U(+B47 zwU_NHcB|m4^JDEy;;YLgzU2H1aR}p%i}~n@u2p_O_LZ)19Kw9;x{di7+PFeHi};E> z;?8`O>kiCE@978db83WP=zQ&A;0t`_?WV*y)Mk-C=g%iz;5x7`#BJpc=Ihwj724Uv zS6bo={;#in04x86I0BqGT=Wa#P*mXRfA?DDhlV(Wap3cA#Ua>N!=21mpmT*bocL;a z)E)bh>kjCMb(LU-fq} zuA^I5Y9ZpQCt2P;fYp4o!UaFk(EQ6BZ!@OMR0r)$`=bx#x+A!n*N^P_39I_iDqoF0 z#X5HH%eaQ8*D4;;vF;nQj@3u8UUGjTEB;;9P5#|#|0?Da-VYtYS4!v@=v=9dBpss* z%yw^=FDo78dPv6AbGPtcHQm}M-M-3+Bw7*?ng%5VO$qoXz&wO_6$C7wBif# z4evuff$IjuzS{k_U!{#ET>d26S4HxB0vUOZbqw4mblkdE*^_kitToR^Mchv)>*z1? zKEvw8h5LoFec8?L8}=^GzK*s+-;+UnbwAB~RqxOKYroxkmA#0su*8>LyZ2h~1^)y4 zvddRSx<3);E&2HStxfqd>JI49+{*Ul={{Gjq5S~OO%>Y*le=FO<8HZ!ab<>nqK%>X z*j2gvSaX!u4>sGc&eskGzQAW*pAzei$U}waVg7vL1+IhqD_YC@eQO_LzIOUuud)x> zeWcgyCz2w6ll_Ep499c%I`Z$HgA4cPWV?r7t$)T`&+9slHR>qacZqyeKUy4LuqW_^ z{j0u*nXmTVbJbeX5&N0IFXEV6_hmNh!aAk}uAxWvDuYSK+K4%BBR^vETJQ@y=xbeTmEX&8NXAwDDC3$jV7xkzbi{rD=;#zK*azkb zaHYTCzOPsGO?Ei7SE(l*LzB!pf^WUvHs(2X()uCJFCU{N>WI45`xx_ec;_ctGwF!? zYoQ~?RqnbL=fya{7wWVwfotNR@#>DGW7og=J__h)x9@9ZUj_PdIf%%Ut3|(X-tb=K zXQX3V_|=N!g@*N7CCNGtX*#M?t&Jxg1OE_phlr0(>A0o-SMUkOHS?hH>dvGi?hAm9 zn9t?*6S93FU(E) zdy;h=J!HJP3+WhhX+CZVSL!LoHMHhaZ6fi7`+l9~OWqHVn~yZ9@qEn01B}ae>Uecm z;wvlh<<#>r3-*}^7y9=-PcyFm*YzsRU~ecj%ktKC!b|piMx80UyzP1S+3KdqsQX8 zQSl=CIaYZN?1P}>{zDvsp9rKF*HN9HYLiLFY|TlYO+u?e1osRL^J%TUf z_puecuVaTNdX-<2j>zw!BlzxXes9%}wyKAqW8HJCV`I%{+7!|;@OXK33|iDDGA_hz z=+PwnmnS}6t)uzqIi+HKrkp82rv{OK&3my|`4#Dy!F>FWc^`rPAs_u<-Aezxod3bT zpkwCWtmAQwpJ`#zQF+209Wl=_HuzP~&&=~m*Ks$4j?fvOEA@WlWRdr$;W~ExMEnTz zc=EVyzL0f{zrZ>k-TIj}m2_-!Nk`NT7)}ls{gUs0y~w!Q7mQbTCmqrM0>8%m-gtjn zx$obGpMV~bcE;uD?o}FSKK5*^Y<`bAt$88iI;!(CZ5ruV{iJz5g73cezpVT!bTH{? z=mS)DFs>O3$E!ae9q~N|(9td~t9(Mn1wRqdwFbVS_&evNsK(N7fH$F#yF=Myqt%FB$)-}t#UopemPq@&zt0xtAd zqXO5=mE+YPl8)$`Ku63Qr~4){u7+2buh|2#%KoGy_A^08w{aoQ=@7V%YW-Y0pLDE! z%IsI|+P&3$gx$h#fG^+*E@r+)_l{S8r0Xc^N9br5mzCXH^-WNBq($7`VfU<|6A3Tt}Xdi8q+9rp_<4i*+4cnve2& z2mEU7FC@N5$DbN>gwB2CD^cWrCR_(`8+Au!8S~Zu)U4tq9Z`3HUt^x*X5A59&bWrw z^k|omj-F@S@vHKB2lzrir#8*F+DA-K_aq(B&jG*2{NBh{x%)Y=d*rJD;lFkml~oQV z9g(jV(s7|-zpvf;5%vN51upb+;)1WgH1=qhl8#-Hj&}PdrS|VpKlxQ4X$Xfuef`e)5{?-XA+uZ#=vvH30LYwWBE>fXdxtb^k= z_;RXFD`;N?68qdU3C1<5c8xZZ_`*JS#BJ>3+ezC0WfhMxejKgr%L-S|kJ;ZxUT0jX z>n5oC5MOw%HTVh$zb)@COj+#r2Ob=)>RPM(9(>e^b@yLiu|}Ikd_`biF4sedkKiLI z^5`E@-7%Q>s{X7p>&VEz>Yn3$wbgI4j*-?cwHAFoF0-f~>HFqhrNe_5~eV_A=Xv&ezWje1Xrr-ISQ$$JZ6NpB&c#u5Q6s>^Qcs zKV0#Rb~W)8c)l|BCFh0pAFz(?y%W@*6JN*+F%HCixAwW$KEU?Xb;o|W`%;!~7_6?U zp>>$I*zUV`^w2IrX58y%^!nix$XIz<~Yqe|0?$iH|pHK|>D$ZA~BltpI z7#+v=ft@vIqPidPh3DUcFQ@WCc|8q&qGb=Z>$>jm`MTD?7x>KcQKJ89684z?yu}M# z2YjI(N`B0^hP1BL<`Ay<9G;JOzf<;QwXT4AD6oQY%{*wL`b*Lg^$>J~eY&-t2EM#s z2);VkYIBLNrn&C$1sxzSbcEeURx+;9Lnf-fBEGQS7koKo_p)ErTbSgflyHh)0dKL# z$h7kKRrz{3zUUvZKGY!mm+#bxY6J0w{l4JK#r2_F{w0swGptvOl6^IZ_<;GCAD6@5 zCk_7vK9u*^zJ5&g(65QF;L8?$asue1AE)XL;Hp2*Y$rNj^9+2+e3rW3Bvzzf#dZ3c zPe9Ku={{5ZyWJz~zU^_&zv8P|$Lh9T?K<7xi+mO1XgGxL3)TAo#=e{){(Vb$tnvxj z-y@&ExDz5idg2q+-;jMpDpU`FFMR)Y`cuJISFd(G@s)Ui^Ly|WHSF6q^3^3hH^qv# z68OrUqT!JPO!sx`eC==G3w-9US7JVqDzYBJb-)*%r%?U5;Hx&P-9UU*zi8$wDAw&| z`wC0z`FZ@(i(>i8;i3?PxE&L?E?zKEJ;31aF%HDna_7;q-GeXmzx=D1uNRNWYBv&J zsU5k`1p6{RKgVcacAuY95SJdZpW=MAOXN9cE}W?TmiS7F{ulUiDxZK3kR5!1j~-DE z?X`Wcb`$Z1{}3O)pO1>kf7zXns7rA@*cbRpOy#=c%;gi+1BtKD=d7dCd|7?(7Whbs zK0vRgL~hpo*HVjqAq~t&KTgMO@KGz`(6wtPs$SwNCHQiCUq?O;iF_i|!}Bro$~rAZ zd}T!bwHYpl^Dn#kMBTpT{0Mey_lW!}Jl%YLov&LAe053rS*iI~SCRP_t^*zO<6gr$ zdg>;r2a|oZ{IxRuRoPE;e95?us9CSwN_+)He8f1M@~g7HhmI-9PISJ0XW%Q(Ck&^= zd?H=z3;#R%t37L3$M(UK)ZY_d=&xcN#{R?*imULecGqiV z9qsxF&-vzg44Lg7VfV2ur?Tshfzy~T zPnL0cqLb7=5w5n=D&tq-C$a(;c-L|H47h+Be=ju-^%Uv9a2?t1BkP&3i|0>L|4g{B z4;k-w%I;-90bIye>ozd1GZ#!!4<%fgFWJ6;%c(eo@j?$7m+v-_M=zYD9!9vjzj6nc zRUQpKlEUuiu9&1APPqKvRAxTf_4oeMo$>cHA9H<7oIfG#%TqmBJ%af1{jIWoBKmjp zxOH4Z47h+Bc3G;Q@T@Ox9U0d_9Kt@n_;)-X+Xqcn{e%no1m2H0=E{1lp>N{b#JH{- zJXt-GaK+cM-2)fqvs-c7dj{(m{+4lh{xn%Vif}2tW?XK?ZM*Za!oui ztBr&U`{nR{r|f=9al1?4I&=PH^%%mHTE}(|T$PI3A&vPuYr$kSK)5^`+`%QsZRm(R zN2y|5XD^(r9;@rP(H&gy*RWss`|2mSzgoRB;~KYovU(ih$~Nqsvp4AIlzmy%9oU!M zvXuR5baGbt9qrq0tI+*vcKvGi(PsYw9qb)6F7gWn)&i%v&x@|ub#Urn}2zSna8c;I@Ev*xbt>XV*b_LSzJAY z>mWYDeuiYc!HqIZ|PRvLDI^_uBt5&sG zS8#Zp4?4CqO7oF$4Kd=9c`0!|Docu+kKjk1kNzFRd^~lX;wM~~k9a@q)9rjBBXG?g zu}(RXa3P-nu1e(-bv43IOk1ZMMY!N6fXm2NU;ISSBJYs%3D_5|8`++5MQ5&4jwW2u z|4~1YKE^y>?D_|M9)1Gn57!Dm5nrbaCBEYKRyJ-&0_Jgh2-h$JF5t#^O6_ARzu(2Q zzbt@KXdK>Z4x1+H8MeCGf40ezA+qL^r<0GycAIP|_S+-6I5HA0Q%EU+Tg?gx3 zWn8mYPF9bnK0w2_=Kh3R{>yIM?mE_Nmy)>@|Lef*O!f!=g}z9$!hBu3cCvZ`@#X!F z`PyuM4qeelKUjA!9zb#LgrC5;n|ESdp6oj1ShBCC`zqrn?CMxQyi7VuG(tzu@#gdE zd>v=t3w-83USgh8SET>Kb)X~0?cGJ_ST{vIQSZxDs825EU%}lNSO0C+E5{RG$iFZS zqhEEh9)gZtlAU;nuagXXfzQ6`7$~xTkL$p%qVJoY&g&f`2d!65Aij_ng0CKtKlSx_ zkHy9z=!kW`w%u9B_Q6xslZh{^^I;rDe{a;W-1~;W7uGvcKVV$ZgQloWgsWTlRp4@} zAC2+CPQaJ{a=u@oX%EH~@~>A;A|10LZbL`(v*qU&1m+c&$5`noKeqt5nn$w#>ZoH} z!Nw`-DY}lEI1Yg?&n|p@9oHjA_gL5=<~hcL_=s`$i23M=PEr3#I>!HA znLG!4b)Ccg?udu^8ar>jaw_o^l=$i~d=IhFuSSZrdn>-==QANbCP$m?MCa=?17F}1 zJeOLhMT(4%xDNQrE@HkCKViP&@%74IiLcBXd*$+O_zC4Wi+zt`KV%-a#f#<>3i~

`%U~mWn34}pQ8Sa_`-de7zaLI?)@fm-voTMEn&Vg0@t>WuUAeZzG^p_=cC>4 z@36W*r64Zi3wcg>Pv+~)1yj`1i7(uz1HPQfbD#s{2Vdz|nXlTt7}rZ3>y^I|Um=OF zwD|r>*?;+k-Qm1e$Bf1IP8Y;w;43b0ow;y|`gh_B_vtvzSHXP>G`Nms%$IL(=4;zG z*DI$JUv&!m)pE_pxK;mG>LWr&>{I9#acJD~DQZxkk7Az!_yXVMo{v^}VeMPYSM^}Q z*Q)i(--)kgi7&hJ(dxNZ$Twk^cJqn!Z+>g)ci_BskBCFiDfuJjE4pHe`VZ1Eu2v@h zf_=r`V;#NqLdSLMl_2TpQO$O5ydT*Zw~M_WIb5XO+to2R#vJeM>W9yRFRbf_e#U$~ zxcdg>AH-K!;wxe^FN|CCPvkg+yb$AV-iL8{s>A9TWM7G3W%I(!$82BmR<4I0{P_mu z4C1T%dal#pSHp%p$5^LX<$KTtM=QRd1Kx-ESUuKkCpuqe8u$XA_*|)ZVYJA+5Z8fy zp+6Dak9BMx6jsk7T_a9J>i)v@Q1w-;<4gVx%2}jimt^;L{Y0dz@cJmm z3q8P>cLdv4!)l253UB2uU;YsX=KKNdD{wUXuizZ^U;EA8poEC8 zjApj4_=$zcxfqm+U9(<~gzP=J;iWr__JX@kL5v9a$0m!W|ZEP(~47 z*gt`|jXr2!zwacuv@l;dFYw#ttNsAT^84KVR=9t+{u|!6of*18yPfWn_NFb?w_V!L z1f9CXdfK(iHYn$ij=ugDc_9(*qaUaGzL<~5b9_f}+-@Inwi?{=`#h&*1^YL|eW&vr z&%AZfXz;%EN_7e~~ zuBYcu#ECD@OBVY?={!FA0bk;@WjjE}{Ql_cIiKji%|>M`@rC^W7zg5*)B7>)`iW4) ztbbn#^Br#f-d^wpe;-}Ue6>&cnYxLdJB+#(@!3UxpNrcVcl;opkEza$+FfK{Z54{! z;0x<%fg6~wu|M0WH0$$Gtf#@g?5?L-t#22|?{g+mdy&~rbiVF3@C82e_EX}%A!UI@ zKA1ltzrb~Jd>QI(*&{?Cl-=+1Ao`-!hEm-q^7ZO%6^A7f{5UC|KWy5r68 z2g(@g7bXs2yGNhXn1319JM89P1?MBth4r+Q;A`8d8a@Bd^O&Ht?hk&f@(HYGbPHVDE!wC| zCBA$&@Om2fvTOHN>uFXxCN5#VyuW9@BD-$V9wxrpUNPI3@j1H2y0+-&=vwe<#TWd! zGW=J${>4k_jmk9Q3+qjK!Z-6QdptJ84)$Pvs}s&T8TM~N@ro0aLW!cSn`Dtsj4TDRM`$^~R!Shs?GA@28e z-KxjJz6!=iLp@Y`6yrLgbE~Qax_wRL`3OFdhnIWbkZkwh3+q;Kf$OFEZ7xZ-jRUHZ#8=NGclauZi$G%Cs(C2m+V9|Rl?d^Lbt~{? zciqa0FROY8_sw}u;yilBpyBE$>fd{x;y9H21^WZ!Nqv2eNU8BL{&!yI3&*%`5^5Vz z^*HGmn{3vxcE|76`HXQpGq7--1AD>Is&8TyA5*G`kBzM3zM*fGi%7?|D(*)^$FTUG zN7+yKi~Rma&z}n0y*wWghu{YiLm1Z~iw9Iaq5IXv%-8=~9E#6yCJw<*U|qCU^b2>m z>|5nx(h=*T&=Gdf*LBh8YenZ1x%i0n;3lyjz|#>{N7A}`@E?^~?|^-QkIZk`zOJ3~ zt#S$R)l;GMN8pN1G~0>J*C+#D;1lz`)b)-;k^8@J9lQCLr}qHU`dl8j%@^RS`JmsL z&hM%Fxmvvg+1K&x?>i1O|GiYc;yV}iTQYoH2l)in6|%>%eYGzStLKo8SXThQ#yDi` z=albEVo>ldm}Y!gb*9abITBiOko@rC`5$EkI9_|@)79JhPKeDpL;Rhvo2 z+A}P0IqX;M#_i^;vvFGy->(3>)A>5rz!&($-%ItYku!_)tGEty#JD{tv)y~@zEdtE z`>IP+Mn}v?_^<9J;lJiiRVNwz7slbX{{ml;QyAAZM|`KW5?`?!IsbCIPJ^ESA4#F( zzT{UY6JOq~E8|z~&d2Vcxh}}h3!5)s_sNs_{E1VA-G{zYt|T2j4_3zRfeYjI|5f1X zo~lkE9a9zZtFW(NlUWZB@zrMF3w-9~DRI9^OObgYt^-_c{mu1`hxiH`_yV7O#g#3x ze#CWh{);Y#ys$dRI`*ITopKfNg}e~sK%V6EzBJ%MofZ?g+Iy#}Q;9FsX&8smuNw2! za@T3Hzfau7>qE0=eW(13_`-8)z?Tu%EWb9|>Wu9*i-Q_m+{sMCPUDZ9sd80;Q#C~*q=`z~Sko{sO7 zYe~nh%EiYVMDS7jH|FaXl;>PPe8sl?-^_EG#+l=6@KFCwcjc8$nN6F0)x%iFRAY73le9h*t?;@#@`;`h<7%HfO}&V8L_Pt2jsDBYd;&TKW}59w z=j$m0U*J=ifl_L{-D9!;C4WBg0@pztLflS{V!kHKpQc_+d?mJL{{_CBirdfuIN>K^ zKF*`th6_JYw@JB<>^}XFh21;c&jDYE+ktZ!*P*S|RZo+S*iR0Aor>FXUrxr=EpW|V zFipLLbWGNmb#w|>!G5%1T_G}>`8uq#y6PF?3;W5P<_qJ6edYL~Uy^fpKGuz4T){=t z)Juu4x>_?|+24P^A7FqXzwi2k1N#B!{Fsmav5f18nyssz)&0a`ULOKqZp}y77xKdF z*^F!U@@eV};tS71hM&NE?rZu6?|d7)sJBN@?NoZRlDxLIxW^~>4ZM|aVr0^ z+s9O{Gv^@~zuhDFf=(?XnXhY3+N9h}Ix5u`ahv|+qaUaE%I6cac-*zkj4RT(P1SSy zeEfg%RX1=!kBsp5p8E6DSu`IzDqIi61Yf}u_`c0QEZ(+iA@LPoQW?94j?GuIj=pnQ zM^AW@5+nP{JZxcK4(Elyl@#|sR!@L^ZCBNy`-!)#_aQrJUx-7fhoX}iSNlQdsk6zx zP!GZWjPcQpdMI^`*$?SD-eS-ZI+JVQ|4OX4l|L7^{)p?qe?dpziNfxOZC~{==@?vE z8M{Y(MBNb#vyQWeoTpw!IwHS^j>vbN-k$^e!n#6M;Oc+bCgoPr5$g)z*BG~r_EqdY z1*<%#K-|vlvx@vktiuSqkJQvuy+S(1Dm))ichpZ~9fPNyr~Z?4MBM=$ovJ$u)@d}u zaQ|aU;94Brq})b2Hi@_m9r1a2AF|#1A7LMu?wF6zvF#+x#~rG=NXOKxm7R~Mha#O~ zeQ3ma>gA*(>LKW8^sBQB^<%N?LnYNi1|3_bvwgi4-=y45I#zGZ@zH4=<@*Bc=Bx1s z%y9ztVfP68f=*p%Vt@wvT!0)7?qF>nFndNsL8xr1~J+$8Sj6M2x` z`Dj%S!EV7b@*L>VHkEN@wi{Trl;&gh|M9E(6X2Z6@9o-G_s!1O7veVR+R!BCYllUf zlsidB)U}w8@PB=+Ypwi5f%uq{G>|ZlTi5YbgO1P{`j^^|PCZdv{{q*6eL;_&^O!GB z$9ZZi&BtiiqCeq$exIWNI>khOf8DZ8%6!tX_N>arA>@VOi{PTv+c2WH^tWu<|_hDzY!EKf=CxMBmn} z=jX&8fp%yV8M=0vuWcQel zm>1yNh549+h&bappK<--iXE$#6JL=xDi|LL8S3rmY{nJbX1aPc*%#_<*q2lFc0nB} zABMkgxQuZ{rzq+@q+@Cu_FvEue%a}Mj@|g^f5_SR2><23i20g5Xu5h0>4cdAO$d`vH>Y#t4rA{R2Q{i)u*mUK*gP?>rgeE{ebzl3ppL$2#S(y?w^i+qB( z_R)`1buDm(8bu$IuBHE{>-eTYN9fFdrT>@MC+~Q&xH=8jvFj%yx0lCHGz@25FmAiJ z+G6Fw1w1$+&w;=9w6T31+PPEJTe^QT(MkLqkrDGps29<5MB;N8S923T&%>#_Q05D`pkqgZ`8up-=c>0!N9<>E zT1VIi>`UJ=L~1GF6u-j17kjMzEAv?F`-^>FjxTyM&fhhGbv*0E5$Y_`5&uEQ@AEIk z^nI+B@far%N2@#<`2gMyTh+RDt5iY3jdaH zC8slAucbd!rqXjLyN_kN4-R3y5clPLqF7v3eBr#{3;6{6V-|iQsi^l;e2hL?K|ett z^Ew{3Z?3+6+53@lA@S97TzUDj(oudMGVCkAE;_U!hpYc0MNJT2SQiDK$Sa+`-wOFe zVx2jk@T9$JhMw1veVOgPTKapb`Gl{17t`}VU`O&1*8yL?v&Hv1XursP{_$=_eTew# z5cwDQf_;|T?jsg`6ZG#})`@*-yQ}J>gbV$9;4Zr#-! zhpyj8RUgymuMd-QXv=P_UH^Hue6!i9bg-j8_UbU!DDOHU=lbDCoU*T@B``UK&s-=1{@ zE~oM@j2C*yxV+afU&9xw>XU@4dMfvsoW@n~`OyZxx&*G~<*ND=;flD#7yP2k7xLB6 z^~~2LD^>Mr!j+bAA+IcVp9y|Z#s&LQZeUzfdR6rq!qt*s|K+rf1>?3s$Ed)yfh2sE za5dDpWB0yBb3X`nkN#KWryL)z8Prcr5w47c3-hM0`|qvtLaX=)9XoDh9VZ;rPkoMX zwe3(|zJeBU6#mD`zJfOiTtoV)|0Z0%T6b_^K3U<)3S1k>zMdys!7Iz_zpVHw_&wJK zyHD)N_I1{Xe(DQ^E9w$ouv_qjxScs%irdtmm}}@yY}QXIF>W^(xsHtM$ZZo}U<-NLwL%%85#)A{<8_aOrp?6chd9^-|M@L#~yBXC{3V7hu8 z;llmyPUG5Ad~CUu`I@(Ix_Uj~QtG%*?li6~#YfL=jBEVz>FN!Ht9myxF8IH4uZwOe zJ|+dO2`i_oHxe$a*Mcvna9PDi#G%0L%-5*i>FP~{E48~jd|Aau#O=158Q07K=c_jp zE<8^Gd|}@7HEvt^d%2GZzl!Vjv@)&(X&oj;xIBAUtPjzY@X?P`>m7Fc_u)I8>E9Dy zxw;nT?-usu37xOrLVRV!I>cuCL>=yvL&xCz2b%gVI<8v{xPY6av)`(e91=V2a%zZI!Reb}z@FaGY_?n03B-JK;in1TMGZBm7tG zU5x9jx#z2Q=sK?CdI-3j@~c~lk8y$P;`!&RcM>kdZQyc>uPwz#-`&jDtR13abibJ8h&GA>qb*}*zaOa6AF%HFwj6=8%{5||?=zivF%#aJz`v_OvubD5r z-zh&~6^DS!dmrN(aq#5bN6$X7y7SQXin@8h82=avXyHf=;n} znXliG|9XJ<3jfB!?rC5?`f(~>mHEm($hgj#+fVHvzOn<|=`&ewuHL!oUDDCJ+^l0j*(EnFc^`77$o*Yb`GkxMaR_=uA7EUbmJ8Gb&ByK$ z%$M8skgQ|Nqm1i}1^v`Tq+?>9JN~Op`o3NGFU+?NvETRL?RTkqk93Tt8P{ffk@i0N zams%ISMXjbZj+7=8gzut1cm=AF>WV|jN7=5tYcsS>o{>?KlNqOQQ66z`6%c2uzTMl z%vaMRj4RT*OV#_NWBl#^j^{i?l8mc;?gi>Yq+`C`7XA}{*{yyw@|?QI#e7`ePklw7 zk1pvb_X}b7&@po|-&gKkyld5mq+{}(%FIXDJ>s_i3Fd3Y{0r2FNymJDLg?sJy$$=o zbO$czm=UXe_5^FrW)eN{ipxTX%!)FotJwY#_zx8>(g zz~2W0=K4X`@neII&^d1}CFVJGPZziU3)hkP@}`)t@yjnzA0r*H&IcV)ue-g@*ClXG z9HgmTq@({a>n>o+IOm3S8p{YwA+cF;(XIXth6D_N%}J|JCqs=IgMU-KtiSj@Xw5 z9i8%Dun)|4;DZ0^5V)rFUZ5sP$NK%*zMR%k&U0j3!RMK;F$ZbttE6M|uI2TsRyxA} zSn-t=xQ=Mtt*V=JtbLdL1a!pb%k94k<~am1ai8d$yuf@Z120q`CmqrEg^qr)uWTpE zCkBvzLA`C2hhqFVTKS2Bd5&S9RsD;MYupe`eNESKetG?>m5!KCzz_Svd`t;kN4D-( zwTg6%{gv}V=!nmkd*9HO@`J!q@cb-{CyL?&Mz1%l}eIai5h`!0p!56Ae>N;i^7j%SQ z?rYq(vimK?q4Zql>#7l&`UdIPCFy9_?yYcPyjJruu!wODtJ%G3weDBvn02&^%SuN% z4k3?*PW7Ts{s&rzd5UywIG{4?Fu;ZV;y$6{x3m>t8R?jLk@?!JP9ws7^aFnn{>ycQ z-NUcey}~*k*0_7sr}}(c<&KVWJ!H3U(($kI^i5=*?c%Dx!x>!Av8j>wS*1naOM2``o@X=;3*Z?aLFsP<@)_qc6m9XfwNaxIY10&?5<4 zaZO!L^D(}lVz_c9hdicM^yPj#><3k!la6)oasIU#U-T&-{W#?(;J*@4v;FEiK4Z`k zI_CzV|F6XUL|2jPFt`qIwH#sYn|Mgav_VJc+*e$QWySSPa2>mTBJ-G;=R9tkFLHi@ z&Vl>+Vz2UiY@c)br|rAxbMn3i~*PTHGyk^roKr!0vGso8yD{1uJ7f(?~V_D z)9+Kd55IN_-;Z3oH`^cTJg4vbh5v$`WEL}DneFzd`hxsK;=iQt8+x5_&6sH3N6&sx5&OCb?on9UryB>GOoP;T40{NJrGQn2)f}zSgx?bsF+b zD;;Z>Fs|_{HT50RG40ZPw6ZVgSpO#DI;?e%sxL{$uuD3^KEN0J1awM>I_-~C*Z!My zZ2N6x>srh=zlcMd$fdqZI=1X)kw??OeDvc~z6!gCj!kc|j>9_lsQQX@^bTVG1%C&= z%iS-;e1eX4^TOB-<~V`#+C74=h9sZAOXOdJYkyevwa%B=#|OSJpZi)r7V9UF=V07f z;a5G?5%qbpd;dra`*Nv%^vq|z+R|)ap86{FJ+k|zWW{jhOaVGoi~Rl%SNyQ*8$Axa zU)lOGdXw3Hbsb+Y=m?$j_FQ6~lQ`479-BXp^a9thJ0ByDo5v$vrs!XT5ASW-?+bsQ z9wODXWMA(a>O#U*zk>ZeaJl90;a5?2WCX71L#ovOkdEHn*-wC9x9ScVSM3MP*O>=J z)DGe+wa(0!Q@E`1FYwiHGe75{`Q$3~1LCXOCB6#g_hk3}Gx)i7f!p}Gcau*Ysm`P4 z1jb%xzPiuizk7%A^HJpeU#X$y=ceT6t@OewK5i+$Prk!C&Kwd^Um_im-^1>W^U=63 z&F+1y$OkYC_%B?yN912V%2yW=uGm49$ya5&ul|_%QdK4LG1-@Y4|nFH%$MCb6x-Jv zC!mAfBl53|_@0co@DrYBM17fb42-Hwo+In%UBNo`BOOG2RroL1Ps`iPmqzy0O?(A@Xkqs>;e7PtR9%btSa%oOS7;^U@?@*jRfMbd z2@6~f*F&;>b*y4s=Pr+^U8G~v!NT7QyLU=QdA|vC^nWZpe}ee>#K0H$%=^m{^XP1m zc{Hw*T2Q(`8~#g&pVypLr3t@{1M|il=6vJiLdJ4{deROEw{7(nlh-r`YG|H z{D|ix_;Skbp#yZZn@@O-E>Av@IETj%T<~8wfA$mMzv?bhUn3pk70M@IU(iYEW?Wm5 zzyF+cOb8v_UU!FIMO|B~uzj`m?yK%a_nkC|?~_jcj`eb?u9fRF@KyVUl;@C+uN!oP z&d|TqJg1?^JO|gYYxlMHn8%aHZS#ffSG#+JUmbjr`Udd@zlw2SKD*#obNh2J?xxSg ze2n&2zaYD>d$O|m1nj=KluzT++DW4#|dJKGlPkgRa zyRSd2xV{{&13!U0I&&BMiL-`Wq%J4E@O&olID!<>-{Z`Gr%-6K#{nf8^|Me4h?7pC%Fx+=i zon>6(W?iJdO?=@#3h-rjK3efwkS`*+`!LS0B5N3z@bk$#7r1u8OeYZ51&q5L~ZBZSB?z z1Vvf2%G#=pVqigm1(5`;ZETA~S~b0V8ZWh>t+KU<@!zkK+SabEm7vw8+LqO7`+sNO z^Q<$+%*WnlR`dIX-H`0ebDsA(&w0;#&di)i^T$6BU+ra@KNg#>dgS$Es*Z~NSsjP` zkMTIPlJ<2p(>N4a&OTAHaY(M0sJPYZ0w|7|d=>3(kv^f-9W3_i`YKbt3Vn4wXP!6f zxY7n(z@2Spo^_^Fj{A^t9yQO2c5q&}WYNLm1HzS>$Z^Eq7wfB5{-xGep|8;Id3W_IoAd$E2^WW{c;GI$Xbxi^DVfQI_qY3fLg>`{P+( zz-^aL;JDzcSbgDsEjV7OUR7Uh@56juv-e;jh_99@>=SnL1>K@us!w$MkbPn`joaTO zpYUE(TA%1to&y6MR=9j`aDPuf&;8LwS#lrZt8KsBKOy}fEyp?4@9XyDw(e;)4j~T) zPWV0I)bU^LkM|#3Ar2y3X&FbS{k~Y;$No|pUyVP@IyUf?@h==dd=Tqi^Hm5p@zwAX zi}BHB|3Vx+FDdyK;p%I^1>9&)zID0oL7azVKX35{=TZA(&yVD|oqp5xAoa&^1M^j~ zJbF&= z?qyuj+oZnb`e&)1OR3IlRlce{tov&hRfvAXSKU-+_&QMCq*dbj>hcQFpK!G~gv+Wv zfqG%EAM=umwcl8 zlG2Xbp$mKWiC*td85!9DUPj+*a$pY)! zx$iNx>oE7fXrH_157zfNbkM%o^heY&>j$yEW>=1NrwJGCmxjN`cu{B_(@J0J zycW2y{^+V?T(jnnb$>v(aQ`phLcUw-`6JqkcmNlC)nCQ9&RRFt{UPDP{j7k?u5nxS z3Fs@W=vRyHb8RF4>exCllV5yF-+Ah*!@{?~4_zkGPLWTH>0wPIG@uxcsl1apCiYUI!Mj*uQ4gAEA5S zV9D2R&HW$3h5JU8DvnmT&|c^)qc8dab-C`xdE9=kb)V~D(tYALoaaD~=r`*47*^I> zaeVdF%D-@2{5^CJeKow#d30^%IQM^vFWjFAd=;xNE53Rew=)oNUe5rI<54e;bBmEw zkA9u?^|_mGKW!dY5r<-5k>|wZ@jImMQ+JPd_aVL_Wy*8l_u4b&cI&tfGT;L4EDw45 zeI&&np% ze7@BA1deNkt6SolGk=2nV8Ye?C+?4Sh4MIe#BRMnSIs!thwDfuKosGz@6nGPhag6xz#ao9@SS{pJv_v z*7KI@G17gy#Jab-52czBmOd9|6vy{D_;d)sS(WAag~$Z1BtIThxkH!pQMSI+FR@^{0qnLlDbdLo8qn{zN%js(Xme*YDU@KQ(`JX#KJNKjwC)2-i>pF5u46kf-ijbJRV~1AXCV z*Er_u=s}0OhY_y8JD*Q|RsYw_bC%B{-#}kDzJI*b*T5s(!-=nkGV80$J>7Jlm=xji z8gK!3mWDj_)s>^Za31(7@(JH0=BsA@5$+L$EBG$!3xAJsztro`jUuY&ab zSzS+yxTcx<3qdW(7kmQ8ubT{?ILbYS`06T?PpJK|-N(45%spVr;ONAdOUu@f0L+Eu8pMl9B08kBX3V%N9p`qN+-kpO`?8|ygn8)XyBb9+`0A`7oYi8P}uzJ>n4JtNsYq z7x+q_%KNwUb!6l9e1U$s@!_}dd#gMe<4}vlwW#6_@jCIz%o3?aU}N1FA8abMl1(5B=AXt(;>tvnYKzwcFF^vmph zSEg|sUz+I=LkU+@!G(6IxN_Y;VTB9r1y1-Ebe%eqah*lii@rf|jGa=Rd;+@1^|gt~ ztgn~mc*LQ^S5n~%?Na&5HI5;R=M_V@;Hy@DQ^dZ zjvVs|oTpfQwfy=7Tj~JlkH{xF0vyL3tL_kci7(_6Xa~kIyYmU?9_>z^Aax)22rucY zxx+$VHrL73@v-Mb#>f1+a-|9=*@#T%>q3*#<6 z23*j6`$W4_AsW=*#mI`?mK~=Bxe*j~GpSwU6NZ z%Wl3@-NRSWZcXZ5OWz^hCVhFY`)v4Xo%GcWJ3V5It}pqVSiAXB=R@$-`hAM85?_Bc z@C81z+R1a>swc;M0_OoP@Zpo=_5-hY#9=yLGx)h~W$_6j0lwOLy7bkG72+M@3%-hW zIOVIw`b6D3=J;phT;vFUS&VD$$bMoR@#Q<3^@Vm| zKc`xsNPdu8o@|w`s&%Gf{mcKVJ@ZGz5qt!tPi&stPmCwN8YEv%#}Ph(c6-j0J`r0X z{!aQzmMPCEHje4Pnfr0JzvlTS(#-q(@iD|PtQ=n>zTPwN1wQe)eCLmmCvx)%oCk44 zyE|vgIEMO(38XLA&&%ug$aB(XGp-%0R*3g?|Jud#A+*D(JO^>?`MX&s8u2yJz!&%| zG>-8c>i{?p@(HZN_~tTSi<(x5e-K|-hXG$sufrgY9TL}$1^vV%;tO#^JDiFm_`*6& z-8|-N^|lq_pTrmHOyJ9|{7aobs>ibzsql zWF2#!`SivCRXRm z@+;ruI!^;%@UQ9%7}tiK{lt;P7wVYctJv|;3O|mEcBr^oC9cLN?iBwfzS7d~!52PX z=(?2^u3qD4@cW3&qwn6+PaH*j`Hx|ru$wQde4_igX_@t?t_wMi7rt<(_=xywoyFrL z`0}6f$$qAthW$A%`TvN6)vFa>E~P)fC%}h4#JC=Kv!6Ix_j}2g)AMcUtLtyvAHC-? zuBun>6dw~`^*8c31isL&La$G=+6SZRt5zqxh;cjkzCGhM;s`#vWuDXg=AGg{#8=($ z@~ra_u1ql+?G8%aYu^6i7}A&L7v&kZi;ZK~etYAXQt~^UFTa5=@R{xZdDd6kbDVGE zJcuLO?ODM6QS&s4|B}9Z(elI*<2L-OvyO4iJ-oj-miP+z85i1N^i|_N(Oi8s*Kr&D z(X+>_6P+*D&`xf1n zh%e+{XopkzSFt|fx5+0kJ|ZvlUB-MhPH7ZX%#`5nh@~`&aC_X`aO*8NX zKC`FE)9+oobDO8(JkS^NujWgbuc|qX!cBZ3{{mmd=3n{lCr5oEd@9!`mMrftP9VPU z{0_9kuKI+U7s6M;NBzajSMx=UqA&3knO&axSF!%pBcDf-)m@3+VBAi=&G&ohkp309 zzrUD4aqO1kHsWaPk2Qw*kYztpa9WMq@J0MN{0r@lN2Gtn8pXjB$DTti;%M_eQRoYN zB)-VF5)btk0pcrotc9;q!-Di}*FHYrN~IM4BEBjNe1T8!oNt|}{psBN3+E|T_iakv zmc^a#n?3_g`>dgR|a|~Hwq8&g**rCFzVizuNJHOUi>RFPeZ%AFPFMc_7^9T zzM{`t=*uD9yMC+ai*U^}-~#S!c=8+{y*ZALI1l1jJ(u%|U_J9SWP79NPjRe1i+!TE zINF&{WN?u`Vth<}mG!l-<}`6eHC-n?lIte1(Tv-!@v+zY`w}dyi*`xAcI@ddPNFzs zT@?JHerEUnXz+zRr{M~YW7SiQVgSVvc@E;}be@C!zU6Ah)ws96IGOmux+wUYKH|Fdq`W^sYThyK33Pve`0vYmzahjaEd6Wq^NnJl9!J?9%TmWA@~~c8 zzl7shzrVjYh2n_yTD#+DwO-qL5Z9v-Upo|@pDh7yCDUMi2wmXjSA2bKJ;P*+1Yu>tJ+>j#aZisFcQ2l#br-hnvcc_-Re7}us51H|bR$CMIBA7wV``EvHmvJ16<;zOL=r@JlC(z1Q)$y@dUyZzN@4Oa#d2Z!6UcYL9IE&)g za$ITiXshuNc?$X!;)wCFMdAw2KhAw5#WDRM>kDzTYkb6UfeXHhc%)*?msYn@45j{9 z=lyKVYXi42uBA-_L=D9;?NA)U%Kg?5N6d#plCS9Qdu5(8W6<&LqlvF@g~d7yH7rQqcCGVe_@d)u z{+Qn8%dBf{UA$5ZBi&>Eh<;(rzl`$^tNu@iHho#eQT0{e@=oKt(0@C}(e=y#aW=&< ze7xDe((*c5^?opQ7WZc}fubL*@T=<`wfYB($fH9CoAVGAN3K7o-Zx*Dsp>v`2lI8q z&H-W$@ztvERqXg^m4B&z4_`&QJEec6?w;m8hIHTkhw`o~K-bY*n6LX*t`uI8P+x6W&A4V)p5Q)?;)v%-BaZOpQrA~;T=WcSQmx9FrO;4?rVk1iZA4= zDT!=X=GfR|Fu$#r8xS|F3PmtAq}b>3mn zmv*0wb2N$J3hcXeie!f4|Oz& zDWui~^UNp0?L$rZm5LWX<2=CCHBP}ralFtNN3|}PC$7Ltx$Sd@o)AaW3q#+O{jvHq z_xaQxQ7V{2KEw<9>i*ubWf(g1!)^wg;Fm56y=zpg0EI7XC#X2kG0c`A|k*hWU2<`;4n` z#wsy^;+S1Wmi@8Vd?Md@E$TUbISyU9ZJ<~{aqK!#`l{@YcIAc82ZbQ>rSj!n%HzPTPlnHJ+VwZ%@pfD3VK zxtQw&(+8dIzL?_Z8eCqVz`A?$L(EszC9A|Fieq-&9pkoPpOrC=UW+_|T4wsP%sZ6N z*Xo}tV*N2T(LCOpK;-d5xP|j6e56oZzMpd5600f=uC|BGxS%ieH@{pTx_99!F2a1cSKl+ju{n6$;I*Uujqg~=k?K<6kiQXSyxAs*R zjjML?Rj9rQaptRgOlkCmX>3az8=R*3~@x9@wt4j7Y*l_N8>!eg>l)pn8)o_ zx-K(H<96zw7WyK9LHf2Uj=-f=GhfY5vhH<#U24$Rr~Dw#c}KPMl`P*DZ*U&y9y;;1 z$^IB$C8m&1#70~Agw6dilYbF*6K3A-R-vMu~uSw}I zx&D2we+Ryxd;e1$$Hr}|#Nm2AA)j}GxP$LP_qpdge*~_i#5I!q{xXVV^U3Bo7K_Vj zp4LnKD^o92AMiXa{WQn%OrFfRkbl|L zAJfWnpP?`8H_h#4V;n8@Oq?3O@{J?-Xp?#LC>n<@C%!sQ zDPtU|L8wPZq~D*gahCgX;wv(Q>rCJ)b{=1spsx=Z`O?nM?Rteg_{xlrez^|Q@e_`t zmR==}Cf)nSSny@@_*kn4zlb_h_#_@zjT$QCec}Zk@91?HTSXD316- zKJiH$T_uep#u1zk<74LpWqhPK9%G0j;*8JbJ3dzbXJ}6Ad^iv0wTMUjr&3?dgTxio zAN{{%ew|*g1z(6$=m(7Js6l7CucSCu4=rQemx6%{#1V1Mo+i(EZGDb)CY+~OpNP*fwP(2cF<-4Q=)Tx|RmBDWf==3g&U~eIo$0=ce4_nN<*7%5ujZNj+?w{Eab51csc~@} z#j#H2tB9lVd2_~mBG>25S;f(69P-aK_bZ*Rg$BOBCv=(bI26xuo`&< z67|Gai>xz&uO2yHFZKNkReh;(^uNfsX3d}Nt|xuPj^X(u;%-+QaokMs=pXp~M+N$Q za+0~f;JC%Us(eLuGhb`>4ibwgj**}=7bj4E>?+fI2ysLmz}Lxf{L218;%bUx_37p~+SMO>-G@x%HOyoEdVa~c zT7Es-eKo}~sl+k*%+SpIL7msObGX*Em}KowD9htnSlC+o*feFV;H}FEL+L+v8#;@rCsc@C9GC zd%XkWHrlO8-D`D~;yTh-@K+Z4vbl~4-Gh&$%vU!*9v3GOU#a6KWX8i!)xT`kJ#h8- z%{tNfT58}6d=eb~%Cnx+kYhau=P6eAu9>B&`=Ysch2Nt-QT1 zue5s~40MlndtYH(T31}0O#1R4W-))XS@#%+kgo<`Wn4>_SBhoCSHqdyAHkPh`6}Xo zI70WHBNW{eU#A%O0-yL?zIkC?j&*XJN98N}JLao?Ri(I|`0~$ohA(v=40MlrwCDGX zYwNzaIF{0r@Fkv^eyRf-!)U!h&)&A-4$ ztc&$^@8s3u4C1T$T#NCM;uNHByXGAjhgwcH=PNp2HyQW>pIO=DnSVtt&+Yn0oTpYl zQ4#Czbw`#)_u2N!H}DDMUx`0)9Cz%k6w8S(n9#(k&qFSNV)kBmzTtroLLU#T}g z8}|YC{h4ts*;3P^%X)Tko)g~7e7$`0YEeUc)yr`Rd>Qp+XPyJTkgs-2Tw7*T ziCc)T)Epik;S%PYRzg9()qfP*WJMvK5uuO3Ao^2{uIaY zx|%9+EAizy+!=kT>uJa*z(@LZ#F46+N%Kc@FgBlH=nzns?kreAUfizMQUq z)#^ekBF_mabu;L;*w?7}whSs>JQYS70Hpi-NDN-Je{q zV8qo`ncFUwI^iyw^Q{Tj6?A^d7c*e2lF-Uk~QK&;wvWmBlt3oLr%=oFduTg$GEDl zUL!6dT<|a8a@xOe-uk~YuBMyThy{eJvrPU4pJ`tMQ37;!?r| zUj;6weYNe2eEo>_0pt4Z3v0v|2$$~y);(|;`Et^~eE(uxRj;lQUnE@cFW_?8zi{5f zKN;6I-drOtBV1jQug_b3qWM&_zd+x`zQR{={C24?&2yLd67khtCSO&3!ut`&aqEb? z#Fqⅆ++Qx_8ni+9a;VDR+s>2^V|u11{hO&-w2Eign~x|H63?N7Tt%Wqsn&x2nWSies|Y ztS{6zRDHGOST|{X$pW8J=gHtAonXDA^}nq9*_9#pb;MVvyeEv zj^KHRw_3z0j-HKWo2O;&ixHd8?e_FxT&aO)yQ37x`ZD`h^dxgUG~#QufiLix4NsnR zreu!$ws9WlUOUH(OXq8ufiLh`D6T|~zKZi?ef4dwBP9>!IPREIE!GfUs57A*j@FsT zS5cRXR4}fy=AZ4pp7@G;*(cBrjQfRNr&H*>HsR-dqH#vGxQqDeJbGfLe}XT&a3K!R z3C5u$^wpR7TDa+K_YK5XV1${kV&{)meBrpj1>GY~od+?lO7i=!5Uy^Ct1S7dL0=vH z7+2$hYOz+2qZ}XYj-$#~txjAK>k84Z*1K_4n#h-2&!=4;OGx$dtLU+H!&lYfCP@a@!nSAeT} zFyr!(-)|zmBI_Afsr=rmKYC9w*TtYO;A)k)=2gyfe~tKR9?5y3-F)?WpHqXrq9=16 zef^$laWC=Ja-1{zf?r$dD>#JXc>er(?pt(yjdF%BHP1mDJLI?>AHcZo**MRAE8%J# zZN`PXve5m$R{FB?d+5t^DC4?zf3;|$IEIgRCXT9qAtwzuxac1wO%ZzUvAdInFz99_R~v`A2XZ�X5zMXJs@_uRf`(pXBs+(B( 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 = packedMsgLen16; - + if(!push16(packedMsgLen16, &pPackedLengthField, end)) return -1; - + if(1) { //quick test @@ -6370,11 +6370,10 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * //SLOT INDICATION -static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_rx_data_indication_t *msg, nfapi_p7_codec_config_t* config) +static uint8_t unpack_nr_slot_indication(uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_nr_slot_indication_scf_t *msg, nfapi_p7_codec_config_t* config) { nfapi_nr_slot_indication_scf_t *pNfapiMsg = (nfapi_nr_slot_indication_scf_t*)msg; - printf("\n"); if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) )) @@ -6406,7 +6405,6 @@ static uint8_t unpack_nr_rx_data_indication(uint8_t **ppReadPackedMsg, uint8_t * { nfapi_nr_rx_data_indication_t *pNfapiMsg = (nfapi_nr_rx_data_indication_t*)msg; - printf("\n"); if (!(pull16(ppReadPackedMsg, &pNfapiMsg->sfn , end) && pull16(ppReadPackedMsg, &pNfapiMsg->slot , end) && pull16(ppReadPackedMsg, &pNfapiMsg->number_of_pdus, end) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index c04285c62e..5960f4af8e 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -1772,7 +1772,7 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); + //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) { diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 23e18f5787..6a77d0e3c3 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -172,7 +172,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ nfapi_nr_ul_dci_request_t *UL_dci_req = Sched_INFO->UL_dci_req; frame_t frame = Sched_INFO->frame; sub_frame_t slot = Sched_INFO->slot; - //printf("Inside nr_schedule_resp SFN:%d, slot:%d \n",Sched_INFO->frame, Sched_INFO->slot); + AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n"); AssertFatal(RC.gNB[Mod_id]!=NULL,"RC.gNB[%d] is null\n",Mod_id); @@ -181,71 +181,69 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ uint8_t number_dl_pdu = (DL_req==NULL) ? 0 : DL_req->dl_tti_request_body.nPDUs; uint8_t number_ul_dci_pdu = (UL_dci_req==NULL) ? 0 : UL_dci_req->numPdus; uint8_t number_ul_tti_pdu = (UL_tti_req==NULL) ? 0 : UL_tti_req->n_pdus; + uint8_t number_tx_data_pdu = (TX_req == NULL) ? 0 : TX_req->Number_of_PDUs; - if (DL_req != NULL && TX_req!=NULL) - LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SLOT:%04d/%d DL_req:SFN/SLO:%04d/%d:dl_pdu:%d tx_req:SFN/SLOT:%04d/%d:pdus:%d;ul_dci %d ul_tti %d\n", - frame,slot, - DL_req->SFN,DL_req->Slot,number_dl_pdu, - TX_req->SFN,TX_req->Slot,TX_req->Number_of_PDUs, - number_ul_dci_pdu,number_ul_tti_pdu); + if (NFAPI_MODE == NFAPI_MONOLITHIC){ + if (DL_req != NULL && TX_req!=NULL) + LOG_D(PHY,"NFAPI: Sched_INFO:SFN/SLOT:%04d/%d DL_req:SFN/SLO:%04d/%d:dl_pdu:%d tx_req:SFN/SLOT:%04d/%d:pdus:%d;ul_dci %d ul_tti %d\n", + frame,slot, + DL_req->SFN,DL_req->Slot,number_dl_pdu, + TX_req->SFN,TX_req->Slot,TX_req->Number_of_PDUs, + number_ul_dci_pdu,number_ul_tti_pdu); - int pdcch_received=0; - gNB->num_pdsch_rnti[slot]=0; - for (int i=0; inumber_of_nr_dlsch_max; i++) { - gNB->dlsch[i][0]->rnti=0; - gNB->dlsch[i][0]->harq_mask=0; - } + int pdcch_received=0; + gNB->num_pdsch_rnti[slot]=0; + for (int i=0; inumber_of_nr_dlsch_max; i++) { + gNB->dlsch[i][0]->rnti=0; + gNB->dlsch[i][0]->harq_mask=0; + } - for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; - LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType); - switch (dl_tti_pdu->PDUType) { - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; + LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType); + switch (dl_tti_pdu->PDUType) { + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_ssb_pdu(gNB,frame,slot, - dl_tti_pdu); + dl_tti_pdu); - break; + break; - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - if(NFAPI_MODE != NFAPI_MODE_VNF) - handle_nfapi_nr_pdcch_pdu(gNB, - frame, slot, - &dl_tti_pdu->pdcch_pdu); - - pdcch_received = 1; + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - break; - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); - handle_nfapi_nr_csirs_pdu(gNB, - frame, slot, - &dl_tti_pdu->csi_rs_pdu); - break; - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + handle_nfapi_nr_pdcch_pdu(gNB, + frame, slot, + &dl_tti_pdu->pdcch_pdu); + pdcch_received = 1; - { + break; + + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + handle_nfapi_nr_csirs_pdu(gNB, + frame, slot, + &dl_tti_pdu->csi_rs_pdu); + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; - AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", - pduIndex,TX_req->pdu_list[pduIndex].num_TLV); + AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", + pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); + } } - } - // if (UL_tti_req!=NULL) memcpy(&gNB->UL_tti_req,UL_tti_req,sizeof(nfapi_nr_ul_tti_request_t)); - if(NFAPI_MODE != NFAPI_MODE_VNF) + for (int i=0;iul_dci_pdu_list[i]); } - - if(NFAPI_MODE != NFAPI_MODE_VNF) + for (int i = 0; i < number_ul_tti_pdu; i++) { switch (UL_tti_req->pdus_list[i].pdu_type) { case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: @@ -264,32 +262,22 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ break; } } - - //printf("Inside NR schedule response SFN/slot %d.%d. \n",frame,slot); - if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) - { - LOG_I(MAC,"SFN/slot %d.%d Sending ul tti req \n",frame,slot); - oai_nfapi_ul_tti_req(UL_tti_req); } - - if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) - { - oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); + + if (NFAPI_MODE == NFAPI_MODE_VNF) { //If VNF, oai_nfapi functions send respective p7 msgs to PNF for which nPDUs is greater than 0 + + if(number_ul_tti_pdu>0) + oai_nfapi_ul_tti_req(UL_tti_req); + + if (number_ul_dci_pdu>0) + oai_nfapi_ul_dci_req(UL_dci_req); + + if (number_dl_pdu>0) + oai_nfapi_dl_tti_req(DL_req); + + if (number_tx_data_pdu>0) + oai_nfapi_tx_data_req(TX_req); + } - if (NFAPI_MODE != NFAPI_MONOLITHIC) - { - if(Sched_INFO->DL_req->dl_tti_request_body.nPDUs>0) - { - Sched_INFO->DL_req->SFN = frame; - Sched_INFO->DL_req->Slot = slot; - oai_nfapi_dl_tti_req(Sched_INFO->DL_req); - } - if (Sched_INFO->TX_req->Number_of_PDUs > 0) - { - oai_nfapi_tx_data_req(Sched_INFO->TX_req); - } - - } - } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index c1dd64af5d..9f40821d04 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -164,7 +164,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id); if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) { - LOG_I(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", + LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n", gNB->Mod_id, frame, slot, gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci, gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 26978ebc30..db3251ae99 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -216,7 +216,15 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { module_id,CC_id, UL_info->rach_ind.number_of_pdus, UL_info->rx_ind.number_of_pdus, UL_info->crc_ind.number_crcs); + handle_nr_rach(UL_info); + + handle_nr_uci(UL_info); + // clear UL DCI prior to handling ULSCH + mac->UL_dci_req[CC_id].numPdus = 0; + handle_nr_ulsch(UL_info); + if (NFAPI_MODE != NFAPI_MODE_PNF) { + if (ifi->CC_mask==0) { ifi->current_frame = UL_info->frame; ifi->current_slot = UL_info->slot; @@ -226,16 +234,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } ifi->CC_mask |= (1<UL_dci_req[CC_id].numPdus = 0; - handle_nr_ulsch(UL_info); - - if (NFAPI_MODE != NFAPI_MODE_PNF) { if (ifi->CC_mask == ((1< Date: Mon, 9 Aug 2021 19:41:22 +0530 Subject: [PATCH 131/185] Code cleanup and documentation update --- .gitlab-ci.yml | 1 - doc/{NFAPI_archi.md => NR_NFAPI_archi.md} | 23 +++++------- executables/nr-gnb.c | 9 +++-- nfapi/nrNFAPI.md | 20 +++++++++-- nfapi/oai_integration/nfapi_pnf.c | 20 +++++------ nfapi/oai_integration/nfapi_pnf.h | 13 +++++-- nfapi/oai_integration/nfapi_vnf.c | 27 ++------------ nfapi/oai_integration/nfapi_vnf.h | 6 ++-- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 2 +- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 13 +++---- nfapi/open-nFAPI/pnf/inc/pnf_p7.h | 2 ++ nfapi/open-nFAPI/pnf/src/pnf_p7.c | 6 ++-- nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c | 10 ++++++ nfapi/open-nFAPI/vnf/src/vnf_p7.c | 22 +++++------- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 10 ++---- .../PHY/LTE_UE_TRANSPORT/dlsch_decoding.c | 10 +++--- openair1/PHY/NR_TRANSPORT/nr_dci_tools.c | 8 ++--- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 2 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 2 -- openair1/SCHED_NR/fapi_nr_l1.c | 36 +++++++++---------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 16 ++++----- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 14 ++++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 8 +---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 8 ++--- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 6 ++++ 26 files changed, 135 insertions(+), 161 deletions(-) delete mode 100644 .gitlab-ci.yml rename doc/{NFAPI_archi.md => NR_NFAPI_archi.md} (76%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 8b13789179..0000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/NFAPI_archi.md b/doc/NR_NFAPI_archi.md similarity index 76% rename from doc/NFAPI_archi.md rename to doc/NR_NFAPI_archi.md index 6bc906f494..2c92f9497d 100644 --- a/doc/NFAPI_archi.md +++ b/doc/NR_NFAPI_archi.md @@ -60,7 +60,7 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { ## P7 UL reception at VNF -Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vnf_p7_start(), the VNF receives and unpacks the uplink indication message received on its socket. Based on the unpacked message, UL_INFO struct on the VNF side gets populated. The NR_UL_indication() function is then called at the VNF, which uses UL_INFO. +Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vnf_p7_start(), the VNF receives and unpacks the uplink indication message received on its socket. Based on the unpacked messages, UL_INFO struct on the VNF side gets populated. ``` @@ -68,17 +68,6 @@ Through the infinite loop [while(vnf_p7->terminate == 0)] running in nfapi_nr_vn if(FD_ISSET(vnf_p7->socket, &rfds)) { vnf_nr_p7_read_dispatch_message(vnf_p7); - - // Call the scheduler - struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - pthread_mutex_lock(&gNB->UL_INFO_mutex); - gNB->UL_INFO.frame = vnf_frame; - gNB->UL_INFO.slot = vnf_slot; - - gNB->UL_INFO.module_id = gNB->Mod_id; - gNB->UL_INFO.CC_id = gNB->CC_id; - gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); - pthread_mutex_unlock(&gNB->UL_INFO_mutex); } ``` @@ -87,7 +76,7 @@ vnf_nr_dispatch_p7_message() is the function that contains the switch on various ## P7 DL Transmission by VNF -DL messages are scheduled at the VNF, through NR_UL_indication() after processing of UL_INFO. The function performing the scheduling of channels (and consequently p7 messages in nFAPI) is gNB_dlsch_ulsch_scheduler(). +DL messages are scheduled at the VNF, through NR_UL_indication(). NR_UL_indication() is called when the SFN/slot in the UL_info structure changes (this acts as a trigger for next slot processing, instead of running a separate clock at the VNF). The SFN/slot at the VNF in UL_info is updated using the slot_indication uplink p7 message, which is sent at the beginning of every slot by the PNF. The slot_indication message contains SFN/slot of the TX_thread, so that the scheduler operates slot_ahead slots ahead of the RX thread. This ensures that UL_tti_req is received before RX slot processing at the PNF. The function NR_schedule_response calls oai_nfapi_[DL P7 msg]_req(), which contains the routines for packing + transmission of scheduled messages through the socket to the PNF. For example, to send the 'TX_data_req' p7 message @@ -109,12 +98,15 @@ graph TD slot_inc -- next slot --> pselect ``` +Note that since DL P7 message reception and TX/RX processing are done on separate threads, there is the issue of the L1 processing threads trying to do their job before the required P7 message is received. In the case of RX processing, since the scheduler operates slot_ahead slots ahead of the RX thread, the required messages conveniently arrive earlier than they are required. However, in the case of TX processing, this cannot be ensured if the scheduler is exactly in sync with the TX thread. + +Therefore, we operate the VNF vnf_slot_ahead (which is currently 2) slots ahead of the PNF. This is to ensure that the DL fapi structures for a particular TX slot are all received before TX processing for that slot. ## P7 DL Reception at PNF Through the infinite loop [while(pnf_p7->terminate == 0)] running in pnf_nr_p7_message_pump(), the PNF receives and unpacks the downlink P7 message received on its socket. Based on the unpacked message, the appropriate message structures are filled in the PNF, and these are used further down the pipeline for processing. -While receiving the DL P7 message, we check whether the message was received within a timing window from which it was sent. The duration of the window can be set by the user (set as a parameter for xnf in the p5 messages). A point to note is that the DL information must be received by the PNF within a timing window at least lesser than the duration of slot_ahead variable (timing_window <= slot_ahead * slot_duration). Ideally, it should be received within a duration significantly lesser than slot_ahead so that there is adequate time for PHY processing. +While receiving the DL P7 message, we check whether the message was received within a timing window from which it was sent. The duration of the window can be set by the user (set as a parameter for xnf in the p5 messages). Note that the DL information must be received by the PNF within a timing window at least lesser than the duration of slot_ahead variable (timing_window <= slot_ahead * slot_duration). ```mermaid @@ -124,7 +116,8 @@ graph TB slot_inc -- next slot --> pselect ``` - +Once the messages are received, they are filled into slot buffers, and are stored until the processing of the slot that they were meant for. + diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 7a8ff0dabe..f09d25e6d7 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -133,7 +133,7 @@ void tx_func(void *param) { } void rx_func(void *param) { - + processingData_L1_t *info = (processingData_L1_t *) param; PHY_VARS_gNB *gNB = info->gNB; int frame_rx = info->frame_rx; @@ -142,7 +142,7 @@ void rx_func(void *param) { int slot_tx = info->slot_tx; sl_ahead = sf_ahead*gNB->frame_parms.slots_per_subframe; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - LOG_D(PHY,"slot rx %d \n", slot_rx); + start_meas(&softmodem_stats_rxtx_sf); // ******************************************************************* @@ -214,7 +214,6 @@ void rx_func(void *param) { gNB->pucch[j]->pucch_pdu.rnti = 0; pucch_removed++; } - #if 0 for (j = 0; j < NUMBER_OF_NR_PDCCH_MAX; j++) gNB->pdcch_pdu[j].frame = -1; @@ -253,7 +252,7 @@ void rx_func(void *param) { stop_meas( &softmodem_stats_rxtx_sf ); LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx); - + // Call the scheduler start_meas(&gNB->ul_indication_stats); @@ -265,7 +264,7 @@ void rx_func(void *param) { gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); stop_meas(&gNB->ul_indication_stats); - + notifiedFIFO_elt_t *res; if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) { diff --git a/nfapi/nrNFAPI.md b/nfapi/nrNFAPI.md index 9b996bbedf..264c0a3b07 100644 --- a/nfapi/nrNFAPI.md +++ b/nfapi/nrNFAPI.md @@ -2,7 +2,7 @@ ## Conributed by 5G Testbed IISc -### Developers: Mahesh K,Gokul S,Aniq U R, Sai Shruthi N, Sudhakar B +### Developers: Gokul S, Mahesh A, Aniq U R ## Procedure to Build gNB and UE @@ -34,7 +34,21 @@ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfap sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d ``` -## Procedure to run NR nFAPI using Hardware +## Procedure to run NR nFAPI using Hardware (tested with USRP x310) -To be updated. +### VNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test + +``` +### PNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi 1 --phy-test + +``` +### UE command +``` +sudo ./nr-uesoftmodem --usrp-args "addr=*USRP_ADDRESS*,clock_source=external,time_source=external" --phy-test --rrc_config_path ../../../ci-scripts/rrc-files + +``` diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 5957f173f3..df32c05b60 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -37,8 +37,6 @@ #include "nfapi_pnf.h" #include "common/ran_context.h" #include "openair2/PHY_INTERFACE/phy_stub_UE.h" -//#include "openair1/PHY/vars.h" -extern RAN_CONTEXT_t RC; #include #include @@ -67,6 +65,7 @@ extern RAN_CONTEXT_t RC; extern void phy_init_RU(RU_t *); extern int config_sync_var; +extern RAN_CONTEXT_t RC; extern pthread_cond_t nfapi_sync_cond; extern pthread_mutex_t nfapi_sync_mutex; @@ -110,8 +109,12 @@ extern void nr_fill_prach_ru(RU_t *ru, int Slot, nfapi_nr_prach_pdu_t *prach_pdu); - - +int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind); +int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind); +int nfapi_pnf_p7_nr_crc_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_crc_indication_t* ind); +int nfapi_pnf_p7_nr_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_srs_indication_t* ind); +int nfapi_pnf_p7_nr_uci_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_uci_indication_t* ind); +int nfapi_pnf_p7_nr_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rach_indication_t* ind); nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus] uint8_t nr_tx_pdus[32][16][4096]; @@ -1146,16 +1149,13 @@ int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, // LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); - //phy_info* phy = (phy_info*)(pnf_p7->user_data); struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; if (proc ==NULL) proc = &gNB->proc.L1_proc; - //int slot_tx = req->Slot + 6; //Ref for PNF is slot_rx, so align slot number with tx thread before passing UL_DCI info + for (int i=0; inumPdus; i++) { - //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); if (req->ul_dci_pdu_list[i].PDUType == 0) { - //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_DCI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); - nfapi_nr_ul_dci_request_pdus_t *ul_dci_req_pdu = &req->ul_dci_pdu_list[i]; + nfapi_nr_ul_dci_request_pdus_t *ul_dci_req_pdu = &req->ul_dci_pdu_list[i]; handle_nfapi_nr_ul_dci_pdu(gNB, req->SFN, req->Slot, ul_dci_req_pdu); } else { @@ -2318,7 +2318,7 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) { oai_nfapi_nr_slot_indication(ind); //copy data from appropriate p7 slot buffers into channel structures for PHY processing - int slot_ret = nfapi_pnf_p7_slot_ind(p7_config_g, p7_config_g->phy_id, sfn, slot); + nfapi_pnf_p7_slot_ind(p7_config_g, p7_config_g->phy_id, sfn, slot); return; } diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 463bd42692..b7ebdb36ea 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -19,8 +19,7 @@ * contact@openairinterface.org */ -#if !defined(NFAPI_PNF_H__) -#define NFAPI_PNF_H__ + extern nfapi_ue_release_request_body_t release_rntis; int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); @@ -28,4 +27,12 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add void oai_subframe_ind(uint16_t sfn, uint16_t sf); void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); -#endif +uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset); + +int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); + diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 8c8a19e883..4ac5ed41be 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -1014,31 +1014,6 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ return 1; } -// void add_slot(uint16_t *frameP, uint16_t *slotP, int offset) -// { -// uint16_t num_slots = 20; // set based on numerlogy (fixing for 1) - -// *frameP = (*frameP + ((*slotP + offset) / num_slots))%1024; - -// *slotP = ((*slotP + offset) % num_slots); -// } - -// uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset) -// { -// uint32_t new_sfnslot; -// // uint16_t sfn = NFAPI_SFNSLOT2SFN(sfnslot); -// // uint16_t slot = NFAPI_SFNSLOT2SLOT(sfnslot); - -// //printf("%s() sfn:%u sf:%u\n", __FUNCTION__, sfn, sf); -// add_slot(&sfn, &slot, offset); - -// new_sfnslot = sfn<<6|slot; - -// //printf("%s() sfn:%u sf:%u offset:%d sfnsf:%d(DEC:%d) new:%d(DEC:%d)\n", __FUNCTION__, sfn, sf, offset, sfnsf, NFAPI_SFNSF2DEC(sfnsf), new_sfnsf, NFAPI_SFNSF2DEC(new_sfnsf)); - -// return new_sfnslot; -// } - //NR phy indication int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { @@ -1053,6 +1028,8 @@ int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { gNB->UL_INFO.slot = vnf_slot; pthread_mutex_unlock(&gNB->UL_INFO_mutex); LOG_D(MAC, "VNF SFN/Slot %d.%d \n", gNB->UL_INFO.frame, gNB->UL_INFO.slot); + + return 1; } int phy_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index f4fd6a2bf9..478956f75c 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -19,9 +19,9 @@ * contact@openairinterface.org */ -#if !defined(NFAPI_VNF_H__) -#define NFAPI_VNF_H__ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port); void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port); -#endif + +uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset); + diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 9c3dd6fd8f..9d245446c8 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -1475,7 +1475,7 @@ typedef enum { //section 3.4.7 rx_data_indication -///table 3-61 +//table 3-61 typedef struct { diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 16b014dcb5..878666dbcf 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -3636,16 +3636,13 @@ static uint8_t pack_nr_uci_indication_body(void* tlv, uint8_t **ppWritePackedMsg printf("Unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE \n"); break; - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &value->pucch_pdu_format_0_1; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: pack_nr_uci_pucch_0_1(&value->pucch_pdu_format_0_1, ppWritePackedMsg, end); break; - } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &value->pucch_pdu_format_2_3_4; - pack_nr_uci_pucch_2_3_4(uci_pdu, ppWritePackedMsg, end); + + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + pack_nr_uci_pucch_2_3_4(&value->pucch_pdu_format_2_3_4, ppWritePackedMsg, end); break; - } } return 1; @@ -6556,7 +6553,7 @@ return 1; static uint8_t unpack_nr_uci_pucch_0_1(nfapi_nr_uci_pucch_pdu_format_0_1_t* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_nr_uci_pucch_pdu_format_0_1_t* value = (nfapi_nr_uci_pucch_pdu_format_0_1_t*)tlv; - uint8_t *ptr = *ppReadPackedMsg; + // uint8_t *ptr = *ppReadPackedMsg; // printf("\n Read P7 message uci_0_1 indication unpack: "); // while(ptr < end){ // printf(" %d ", *ptr); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 1e2e2fa21d..82533d0b97 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -158,5 +158,7 @@ pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pn void pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, pnf_p7_rx_message_t* msg); void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint32_t delta); +int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* header, uint32_t msg_len); + #endif /* _PNF_P7_H_ */ diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 5960f4af8e..092b967189 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -940,7 +940,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. - pnf_p7->sfn = sfn_tx; //gokul + pnf_p7->sfn = sfn_tx; pnf_p7->slot = slot_tx; uint32_t rx_slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); @@ -1142,7 +1142,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl else { pnf_p7->timing_info_ms_counter++; - } //gokul + } } @@ -1772,7 +1772,7 @@ void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ current tx sfn/slot:%d.%d p7 msg sfn/slot: %d.%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, pnf_p7->sfn,pnf_p7->slot, req->SFN, req->Slot, buffer_index); if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) { diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index a5cd9bcd16..0db1feb398 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -175,7 +175,17 @@ int nfapi_pnf_p7_rach_ind(nfapi_pnf_p7_config_t* config, nfapi_rach_indication_t pnf_p7_t* _this = (pnf_p7_t*)(config); return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_rach_indication_t)); } +int nfapi_pnf_p7_srs_ind(nfapi_pnf_p7_config_t* config, nfapi_srs_indication_t* ind) +{ + if(config == NULL || ind == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return -1; + } + pnf_p7_t* _this = (pnf_p7_t*)(config); + return pnf_p7_pack_and_send_p7_message(_this, (nfapi_p7_message_header_t*)ind, sizeof(nfapi_srs_indication_t)); +} int nfapi_pnf_p7_sr_ind(nfapi_pnf_p7_config_t* config, nfapi_sr_indication_t* ind) { if(config == NULL || ind == NULL) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 4b68f016a8..2c98cb538b 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -1473,7 +1473,7 @@ void vnf_handle_nr_slot_indication(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf { if(vnf_p7->_public.nr_slot_indication) { - (vnf_p7->_public.nr_slot_indication)(&ind); //gokul + (vnf_p7->_public.nr_slot_indication)(&ind); } } @@ -1982,7 +1982,7 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 phy->zero_count, phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ - phy->sfn = new_sfn; + phy->sfn = new_sfn; phy->slot = new_slot; } } @@ -1998,7 +1998,7 @@ void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 phy->previous_t1 = ind.t1; phy->previous_t2 = ind.t2; } - } +} void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { @@ -2034,9 +2034,7 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) -{ - uint8_t uplink_slots[6] = {7,8,9,17,18,19}; - uint8_t is_uplink_slot = 0; +{ if (pRecvMsg == NULL || vnf_p7 == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_timing_info: NULL parameters\n"); @@ -2055,20 +2053,16 @@ void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) //int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf); int16_t vnf_pnf_sfnslot_delta = NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot) - NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta); + // Panos: Careful here!!! Modification of the original nfapi-code //if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1) //printf("VNF-PNF delta - %d", vnf_pnf_sfnslot_delta); - for (int i = 0; i < 6; i++){ - if (vnf_p7->p7_connections[0].slot == uplink_slots[i]) - is_uplink_slot = 1; - } - if ((vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) && is_uplink_slot == 0) + if (vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnslot_delta,NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot),NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot)) ; // Panos: Careful here!!! Modification of the original nfapi-code - vnf_p7->p7_connections[0].sfn = ind.last_sfn; - vnf_p7->p7_connections[0].slot = ind.last_slot; - //printf("VNF SFN/slot modified"); + // vnf_p7->p7_connections[0].sfn = ind.last_sfn; + // vnf_p7->p7_connections[0].slot = ind.last_slot; } } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 5c0ff7b068..2137965a7e 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -99,8 +99,7 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) { struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; - uint8_t temp_slot; - uint16_t vnf_frame; uint8_t vnf_slot; + uint8_t prev_slot = 0; if(config == 0) return -1; @@ -174,7 +173,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) struct timespec slot_start; // clock_gettime(CLOCK_MONOTONIC, &sf_start); clock_gettime(CLOCK_MONOTONIC, &slot_start); - long millisecond = slot_start.tv_nsec / 1e6; //Check if we have to change //long millisecond = slot_start.tv_nsec / 0.5e6; // sf_start = timespec_add(sf_start, sf_duration); slot_start = timespec_add(slot_start, slot_duration); @@ -216,7 +214,7 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) pselect_timeout = timespec_sub(slot_start, pselect_start); } - if(setup_time > 10 && temp_slot != gNB->UL_INFO.slot){ + if(setup_time > 10 && prev_slot != gNB->UL_INFO.slot){ //Call the scheduler pthread_mutex_lock(&gNB->UL_INFO_mutex); @@ -224,7 +222,7 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) gNB->UL_INFO.CC_id = gNB->CC_id; gNB->if_inst->NR_UL_indication(&gNB->UL_INFO); pthread_mutex_unlock(&gNB->UL_INFO_mutex); - temp_slot = gNB->UL_INFO.slot; + prev_slot = gNB->UL_INFO.slot; } selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); @@ -266,8 +264,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) curr->slot++; } //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); - vnf_frame = curr->sfn; - vnf_slot = curr->slot; //vnf_nr_sync(vnf_p7, curr); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c index a82356f16a..39900113b7 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c @@ -780,11 +780,11 @@ int dlsch_encoding_SIC(PHY_VARS_UE *ue, for (r=0; rharq_processes[harq_pid]->C; r++) { #ifdef DEBUG_DLSCH_CODING - // printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", - // r, - // G, - // Kr*3, - // mod_order,nb_rb); + printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", + r, + G, + Kr*3, + mod_order,nb_rb); #endif start_meas(rm_stats); #ifdef DEBUG_DLSCH_CODING diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index c04bb308e2..c562dfaa41 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -211,8 +211,8 @@ int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type) { for (i=0; ipdcch_pdu[i].frame,gNB->pdcch_pdu[i].slot,first_free_index); if ((gNB->pdcch_pdu[i].frame == frame) && - (gNB->pdcch_pdu[i].slot==slot)) {return i;} - else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) {first_free_index=i;} + (gNB->pdcch_pdu[i].slot==slot)) return i; + else if ( gNB->pdcch_pdu[i].frame==-1 && first_free_index==-1) first_free_index=i; } if (type == SEARCH_EXIST) return -1; @@ -227,7 +227,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu_rel15; NR_gNB_DLSCH_t *dlsch; - //printf("find pdcch from nr_fill_dci \n"); + int pdcch_id = find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST_OR_FREE); AssertFatal(pdcch_id>=0 && pdcch_idpdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); @@ -285,7 +285,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu) { nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - //printf("find ul dci from fill_ul_dci \n"); + int pdcch_id = find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST_OR_FREE); AssertFatal(pdcch_id>=0 && pdcch_idul_pdcch_pdu[pdcch_id].pdcch_pdu,(void*)pdcch_pdu,sizeof(*pdcch_pdu)); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index e01adc1bf2..2ae2549df3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -292,7 +292,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); - LOG_I(NR_PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,mod_order); + LOG_D(NR_PHY,"dlsch coding A %d G %d (nb_rb %d, nb_symb_sch %d, nb_re_dmrs %d, length_dmrs %d, mod_order %d)\n", A,G, nb_rb,nb_symb_sch,nb_re_dmrs,length_dmrs,mod_order); if (A > 3824) { // Add 24-bit crc (polynomial A) to payload diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 9492f3a402..3aad4980bc 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -431,7 +431,7 @@ void nr_processULSegment(void* arg) { if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) { #ifdef PRINT_CRC_CHECK - LOG_D(PHY, "Segment %d CRC OK\n",r); + LOG_I(PHY, "Segment %d CRC OK\n",r); #endif rdata->decodeIterations = no_iteration_ldpc; } else { diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 70a0d419c9..0bace9dbed 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -88,8 +88,6 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - // if (NFAPI_MODE == NFAPI_MODE_PNF) - // gNB->pucch[0]->active = 0; int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); AssertFatal( (id>=0) && (idnumDlDci:%d\n",frame,slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); + LOG_D(PHY,"Frame %d, Slot %d: DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, pdcch_pdu->pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure // gNB->pdcch_pdu = pdcch_pdu; @@ -118,7 +118,7 @@ void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu) { - LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); + LOG_D(PHY,"Frame %d, Slot %d: UL DCI processing - proc:slot_tx:%d pdcch_pdu_rel15->numDlDci:%d\n",frame,slot, slot, ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15.numDlDci); // copy dci configuration into gNB structure // gNB->ul_dci_pdu = ul_dci_request_pdu; @@ -203,39 +203,35 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType); switch (dl_tti_pdu->PDUType) { case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - - handle_nr_nfapi_ssb_pdu(gNB,frame,slot, + handle_nr_nfapi_ssb_pdu(gNB,frame,slot, dl_tti_pdu); - - break; + break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - handle_nfapi_nr_pdcch_pdu(gNB, frame, slot, &dl_tti_pdu->pdcch_pdu); pdcch_received = 1; - - break; + break; case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); handle_nfapi_nr_csirs_pdu(gNB, frame, slot, &dl_tti_pdu->csi_rs_pdu); - break; + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; - uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; - AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", - pduIndex,TX_req->pdu_list[pduIndex].num_TLV); - uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - if(NFAPI_MODE != NFAPI_MODE_VNF) - handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); - + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15; + uint16_t pduIndex = pdsch_pdu_rel15->pduIndex; + AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", + pduIndex,TX_req->pdu_list[pduIndex].num_TLV); + uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; + if(NFAPI_MODE != NFAPI_MODE_VNF) + handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); + break; } } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 9f40821d04..172fdd354b 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -148,15 +148,15 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1); - for (int i=0; iLmax; i++) { - if (gNB->ssb[i].active) { - nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[i].ssb_pdu); - gNB->ssb[i].active = false; - } + for (int i=0; iLmax; i++) { + if (gNB->ssb[i].active) { + nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[i].ssb_pdu); + gNB->ssb[i].active = false; } + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0); - //printf("find pdcch from TX func \n"); + int pdcch_pdu_id=find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST); int ul_pdcch_pdu_id=find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST); @@ -568,7 +568,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { for (int i=0;ipucch[i]; if (pucch) { - LOG_D(PHY, "SFN/slot = %d.%d, pucch[%d]->active = %d \n", frame_rx, slot_rx, i,pucch->active); if ((pucch->active == 1) && (pucch->frame == frame_rx) && (pucch->slot == slot_rx) ) { @@ -598,9 +597,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; - //printf("SFN/slot %d.%d pucch active of index %d set to 0. \n", frame_rx, slot_rx, i); pucch->active = 0; - //printf("Decode pucch num ucis +=1 in %d.%d \n",frame_rx,slot_rx); break; case 2: num_ucis = gNB->UL_INFO.uci_ind.num_ucis; @@ -617,7 +614,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch_pdu); gNB->UL_INFO.uci_ind.num_ucis += 1; - //printf("SFN/slot %d.%d pucch active of index %d set to 0. \n", frame_rx, slot_rx, i); pucch->active = 0; break; default: diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 5e474f1bd2..5bb1ccd1e4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -60,7 +60,7 @@ uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; -uint8_t first_sched_entry = 1; +uint8_t vnf_first_sched_entry = 1; void clear_mac_stats(gNB_MAC_INST *gNB) { memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t)); @@ -400,18 +400,19 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); - //first entry + /*VNF first entry into scheduler. Since frame numbers for future_ul_tti_req of some future slots + will not be set before we encounter them, set them here */ + if (NFAPI_MODE == NFAPI_MODE_VNF){ - if(first_sched_entry == 1) + if(vnf_first_sched_entry == 1) { - printf("First sched entry at slot %d \n", slot); for (int i = 0; iUL_tti_req_ahead[CC_id][i].SFN = (frame + 1) % 1024; else gNB->UL_tti_req_ahead[CC_id][i].SFN = frame; } - first_sched_entry = 0; + vnf_first_sched_entry = 0; } } } @@ -442,7 +443,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, schedule_nr_prach(module_idP, f, s); } - // This schedule SR + // This schedule SR nr_sr_reporting(module_idP, frame, slot); // Schedule CSI-RS transmission @@ -459,7 +460,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, } // This schedules the DCI for Uplink and subsequently PUSCH - nr_schedule_ulsch(module_idP, frame, slot); // This schedules the DCI for Downlink and PDSCH diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 139b22788d..79d8ce64e6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1036,7 +1036,6 @@ static NR_UE_harq_t *find_harq(module_id_t mod_id, frame_t frame, sub_frame_t sl harq->feedback_slot, frame, slot); - //printf("handling harq \n"); remove_front_nr_list(&sched_ctrl->feedback_dl_harq); handle_dl_harq(mod_id, UE_id, pid, 0); pid = sched_ctrl->feedback_dl_harq.head; @@ -1076,14 +1075,12 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; - //printf("handle uci 0_1 find harq SFN/slot %d.%d \n",frame,slot); NR_UE_harq_t *harq = find_harq(mod_id, frame, slot, UE_id); if (!harq) break; DevAssert(harq->is_waiting); const int8_t pid = sched_ctrl->feedback_dl_harq.head; remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - //printf("handling harq \n"); handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); } } @@ -1152,6 +1149,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, } } + // function to update pucch scheduling parameters in UE list when a USS DL is scheduled // this function returns an index to NR_sched_pucch structure // currently this structure contains PUCCH0 at index 0 and PUCCH2 at index 1 @@ -1193,7 +1191,6 @@ int nr_acknack_scheduling(int mod_id, __func__, pucch->csi_bits); /* if the currently allocated PUCCH of this UE is full, allocate it */ - if (pucch->dai_c == 2) { /* advance the UL slot information in PUCCH by one so we won't schedule in * the same slot again */ @@ -1223,7 +1220,6 @@ int nr_acknack_scheduling(int mod_id, /* if the UE's next PUCCH occasion is after the possible UL slots (within the * same frame) or wrapped around to the next frame, then we assume there is * no possible PUCCH allocation anymore */ - if ((pucch->frame == frame && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)) || (pucch->frame == frame + 1)) @@ -1235,10 +1231,8 @@ int nr_acknack_scheduling(int mod_id, get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); /* there is a HARQ. Check whether we can use it for this ACKNACK */ - if (pucch->dai_c > 0) { /* this UE already has a PUCCH occasion */ - LOG_I(MAC,"pucch->frame = %d,frame=%d \n",pucch->frame,frame); DevAssert(pucch->frame == frame); // Find the right timing_indicator value. diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 9aa757d9d4..fbd8a4b5ca 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -32,7 +32,6 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "executables/softmodem-common.h" #include "common/utils/nr/nr_common.h" -#include "nfapi/oai_integration/vendor_ext.h" #include @@ -1346,11 +1345,9 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) sched_ctrl->SR = false; int8_t harq_id = sched_pusch->ul_harq_pid; - if (harq_id < 0) { /* PP has not selected a specific HARQ Process, get a new one */ harq_id = sched_ctrl->available_ul_harq.head; - //printf("SFN/slot %d.%d harq id = %d \n", frame, slot, harq_id); AssertFatal(harq_id >= 0, "no free HARQ process available for UE %d\n", UE_id); @@ -1358,8 +1355,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) sched_pusch->ul_harq_pid = harq_id; } else { /* PP selected a specific HARQ process. Check whether it will be a new - * transmission or a retransmission, and remove from the corresponding - * list */ + * transmission or a retransmission, and remove from the corresponding + * list */ if (sched_ctrl->ul_harq_processes[harq_id].round == 0) remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); else @@ -1370,7 +1367,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); cur_harq->feedback_slot = sched_pusch->slot; cur_harq->is_waiting = true; - int rnti_types[2] = { NR_RNTI_C, 0 }; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index db3251ae99..16bffb14f4 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -48,6 +48,12 @@ extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind); extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); +int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); extern uint8_t nfapi_mode; extern uint16_t sf_ahead; extern uint16_t sl_ahead; From 37e7db80a3a9ff7f026f20c8c875b360a8c138ce Mon Sep 17 00:00:00 2001 From: Mahesh Date: Tue, 10 Aug 2021 14:22:50 +0530 Subject: [PATCH 132/185] documentation typo, build error, pack/unpack bug fix --- doc/NR_NFAPI_archi.md | 2 +- nfapi/oai_integration/nfapi_pnf.c | 3 +++ nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 4 ++-- openair1/SCHED/nfapi_lte_dummy.c | 4 ++++ openair1/SCHED/nfapi_nr_dummy.c | 4 ++++ openair1/SCHED_NR/fapi_nr_l1.c | 1 - openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 12 ++++++------ 7 files changed, 20 insertions(+), 10 deletions(-) diff --git a/doc/NR_NFAPI_archi.md b/doc/NR_NFAPI_archi.md index 2c92f9497d..59c511fb52 100644 --- a/doc/NR_NFAPI_archi.md +++ b/doc/NR_NFAPI_archi.md @@ -112,7 +112,7 @@ While receiving the DL P7 message, we check whether the message was received wit graph TB pselect[PNF socket pselect] -- timed out : end of slot --> slot_inc[Increment sfn/slot]; - pselect[PNF socket pselect] -- DL p7 xyz msg recvd --> msg_recvd[Read message pnf_nr_nfapi_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Unpack Message pnf_handle_nr_xyz] --> fill_pnf_p7[Fill pnf_p7 global structure pnf_handle_nr_xyz] --Data from pnf_p7 struct copied to fapi structures using pnf_phy_***_req. Called every slot from oai_slot_ind-->pselect; + pselect[PNF socket pselect] -- DL p7 xyz msg recvd --> msg_recvd[Read message pnf_nr_nfapi_p7_read_dispatch_message] --> header_unpack[Unpack Header] -- switch cases on header --> unpack_msg[Unpack Message pnf_handle_nr_xyz] --> fill_pnf_p7[Fill pnf_p7 global structure pnf_handle_nr_xyz] --Data from pnf_p7 struct copied to fapi structures using pnf_phy_***_req. Called every slot from handle_nr_slot_ind-->pselect; slot_inc -- next slot --> pselect ``` diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index df32c05b60..2cbec1a050 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -92,6 +92,9 @@ extern void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, uint8_t *sdu); extern void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu); +extern void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu); extern void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index 878666dbcf..bc569c3d1b 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -708,7 +708,7 @@ static uint8_t pack_dl_tti_request_body_value(void* tlv, uint8_t **ppWritePacked { nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)tlv; - if(!(push16(value->PDUSize, ppWritePackedMsg, end) && + if(!(push32(value->PDUSize, ppWritePackedMsg, end) && push16(value->PDUType, ppWritePackedMsg, end) )) return 0; @@ -4607,7 +4607,7 @@ static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8 { nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)msg; - if(!(pull16(ppReadPackedMsg, &value->PDUSize, end) && + if(!(pull32(ppReadPackedMsg, &value->PDUSize, end) && pull16(ppReadPackedMsg, &value->PDUType, end) )) return 0; diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index 9562e2de30..7d1e7e7684 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -17,6 +17,10 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu){ } +void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ + } int l1_north_init_gNB(void){return 0;} uint8_t slot_ahead=6; diff --git a/openair1/SCHED/nfapi_nr_dummy.c b/openair1/SCHED/nfapi_nr_dummy.c index db20017fb8..1286a4e48a 100644 --- a/openair1/SCHED/nfapi_nr_dummy.c +++ b/openair1/SCHED/nfapi_nr_dummy.c @@ -17,6 +17,10 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu){ } +void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ + } int l1_north_init_gNB(void){return 0;} uint8_t slot_ahead=6; diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 4c1dd7ebdd..fa762fa5b8 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -229,7 +229,6 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; - if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); break; } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 16bffb14f4..dcd469f363 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -48,12 +48,12 @@ extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind); extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); -int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); -int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); -int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); -int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); -int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); -int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); +extern int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); +extern int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); +extern int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); +extern int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); +extern int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); +extern int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); extern uint8_t nfapi_mode; extern uint16_t sf_ahead; extern uint16_t sl_ahead; From 49fc03a65ebd9529beefdb904287f86df30dd699 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Wed, 11 Aug 2021 13:16:32 +0530 Subject: [PATCH 133/185] Cleanup and some minor bugfixes --- nfapi/open-nFAPI/nfapi/src/nfapi_p7.c | 6 +- nfapi/open-nFAPI/vnf/src/vnf_p7.c | 4 +- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 88 +-------------------- openair2/GNB_APP/gnb_app.c | 37 ++++----- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 8 +- 5 files changed, 30 insertions(+), 113 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index bc569c3d1b..6111b69bf9 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -3523,7 +3523,7 @@ static uint8_t pack_nr_rach_indication(void *msg, uint8_t **ppWritePackedMsg, ui if (!(push16(pNfapiMsg->sfn , ppWritePackedMsg, end) && push16(pNfapiMsg->slot , ppWritePackedMsg, end) && - push16(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) + push8(pNfapiMsg->number_of_pdus, ppWritePackedMsg, end) )) return 0; @@ -3748,11 +3748,11 @@ int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packe break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - result = pack_nr_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + result = pack_nr_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); break; case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index 2c98cb538b..e390031554 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -2214,11 +2214,11 @@ void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7 break; case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); break; case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - vnf_handle_nr_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + vnf_handle_nr_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); break; case NFAPI_UE_RELEASE_RESPONSE: diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 2137965a7e..4878150330 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -153,31 +153,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) //struct timespec original_pselect_timeout; struct timespec pselect_timeout; pselect_timeout.tv_sec = 100; - pselect_timeout.tv_nsec = 0; // ns in a 0.5 ms - //pselect_timeout.tv_nsec = 500000; + pselect_timeout.tv_nsec = 0; - struct timespec pselect_start; - struct timespec pselect_stop; - - -// struct timespec sf_duration; //Change to slot_duration? -// sf_duration.tv_sec = 0; -// sf_duration.tv_nsec = 0.5e6; // We want 1ms pause //We want 0.5 ms pause for NR - struct timespec slot_duration; - slot_duration.tv_sec = 0; - //slot_duration.tv_nsec = 0.5e6; - slot_duration.tv_nsec = 0.5e6; - - -// struct timespec sf_start; //Change to slot_start? - struct timespec slot_start; -// clock_gettime(CLOCK_MONOTONIC, &sf_start); - clock_gettime(CLOCK_MONOTONIC, &slot_start); - //long millisecond = slot_start.tv_nsec / 0.5e6; -// sf_start = timespec_add(sf_start, sf_duration); - slot_start = timespec_add(slot_start, slot_duration); - - NFAPI_TRACE(NFAPI_TRACE_INFO, "next slot will start at %d.%d\n", slot_start.tv_sec, slot_start.tv_nsec); struct timespec ref_time; clock_gettime(CLOCK_MONOTONIC, &ref_time); uint8_t setup_time; @@ -195,26 +172,8 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) struct timespec curr_time; clock_gettime(CLOCK_MONOTONIC, &curr_time); setup_time = curr_time.tv_sec - ref_time.tv_sec; - - clock_gettime(CLOCK_MONOTONIC, &pselect_start); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec); - - if((pselect_start.tv_sec > slot_start.tv_sec) || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) - { - // overran the end of the subframe we do not want to wait - pselect_timeout.tv_sec = 0; - pselect_timeout.tv_nsec = 0; - LOG_D(MAC, "Slot overrun detected \n"); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "Slot overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); - } - else - { - // still time before the end of the subframe wait - pselect_timeout = timespec_sub(slot_start, pselect_start); - } - - if(setup_time > 10 && prev_slot != gNB->UL_INFO.slot){ + if(setup_time > 10 && prev_slot != gNB->UL_INFO.slot){ //Give the VNF sufficient time to setup before starting scheduling //Call the scheduler pthread_mutex_lock(&gNB->UL_INFO_mutex); @@ -226,53 +185,12 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) } selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); - - clock_gettime(CLOCK_MONOTONIC, &pselect_stop); nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; if(selectRetval == 0) { - // pselect timed out - - // calculate the start of the next slot - - slot_start = timespec_add(slot_start, slot_duration); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec); - if (slot_start.tv_nsec > 1e9) - { - slot_start.tv_sec++; - slot_start.tv_nsec-=1e9; - } - else if (slot_start.tv_nsec < 0) - { - slot_start.tv_sec--; - slot_start.tv_nsec+=1e9; - } - - vnf_p7->slot_start_time_hr = vnf_get_current_time_hr(); - - while(curr != 0) - { - if (curr->slot == 19) - { - curr->sfn = (curr->sfn + 1) % 1024; - curr->slot=0; - } - else - { - curr->slot++; - } - //printf("Frame = %d, slot = %d in VNF main loop. \n",curr->sfn,curr->slot); - - //vnf_nr_sync(vnf_p7, curr); - - (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); //hardcoded sync - - curr = curr->next; - } - send_mac_slot_indications(vnf_p7); - + // pselect timed out, continue } else if(selectRetval > 0) { diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 85617c4073..5104021399 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -219,29 +219,30 @@ void *gNB_app_task(void *args_p) //registered_gnb = 0; __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); } -if (RC.nb_nr_inst > 0) { - if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + + if (RC.nb_nr_inst > 0) { + if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { - if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { - LOG_E(F1AP, "Create task for F1AP CU failed\n"); - AssertFatal(1==0,"exiting"); - } - } + if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { + LOG_E(F1AP, "Create task for F1AP CU failed\n"); + AssertFatal(1==0,"exiting"); + } + } - if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { + if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { - if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) { - LOG_E(F1AP, "Create task for F1AP DU failed\n"); - AssertFatal(1==0,"exiting"); + if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) { + LOG_E(F1AP, "Create task for F1AP DU failed\n"); + AssertFatal(1==0,"exiting"); + } + // configure F1AP here for F1C + LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); + msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_SETUP_REQ); + RCconfig_NR_DU_F1(msg_p, 0); + + itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); } - // configure F1AP here for F1C - LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); - msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_SETUP_REQ); - RCconfig_NR_DU_F1(msg_p, 0); - - itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); } -} do { // Wait for a message itti_receive_msg (TASK_GNB_APP, &msg_p); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index dcd469f363..58a477aa36 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -61,7 +61,7 @@ extern uint16_t sl_ahead; void handle_nr_rach(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->rach_ind.number_of_pdus>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + LOG_D(PHY,"UL_info->UL_info->rach_ind.number_of_pdus:%d SFN/Slot:%d.%d \n", UL_info->rach_ind.number_of_pdus, UL_info->rach_ind.sfn,UL_info->rach_ind.slot); oai_nfapi_nr_rach_indication(&UL_info->rach_ind); UL_info->rach_ind.number_of_pdus = 0; } @@ -113,14 +113,12 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) break; case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - //printf("handle uci format 0_1 \n"); const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - //printf("handle uci format 2_3_4 \n"); const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); break; @@ -137,13 +135,13 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) { if(NFAPI_MODE == NFAPI_MODE_PNF) { if (UL_info->crc_ind.number_crcs>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); + LOG_D(PHY,"UL_info->UL_info->crc_ind.number_crcs:%d CRC_IND:SFN/Slot:%d.%d\n", UL_info->crc_ind.number_crcs, UL_info->crc_ind.sfn, UL_info->crc_ind.slot); oai_nfapi_nr_crc_indication(&UL_info->crc_ind); UL_info->crc_ind.number_crcs = 0; } if (UL_info->rx_ind.number_of_pdus>0) { - //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); + LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/Slot:%d.%d \n", UL_info->rx_ind.number_of_pdus, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); oai_nfapi_nr_rx_data_indication(&UL_info->rx_ind); UL_info->rx_ind.number_of_pdus = 0; } From f74b928d8078e3e0de53410b858da28062f3659a Mon Sep 17 00:00:00 2001 From: Mahesh Date: Wed, 11 Aug 2021 13:22:16 +0530 Subject: [PATCH 134/185] Moved documentation to doc folder --- nfapi/nrNFAPI.md => doc/RUN_NR_NFAPI.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename nfapi/nrNFAPI.md => doc/RUN_NR_NFAPI.md (97%) diff --git a/nfapi/nrNFAPI.md b/doc/RUN_NR_NFAPI.md similarity index 97% rename from nfapi/nrNFAPI.md rename to doc/RUN_NR_NFAPI.md index 264c0a3b07..ea7c2590c7 100644 --- a/nfapi/nrNFAPI.md +++ b/doc/RUN_NR_NFAPI.md @@ -1,6 +1,6 @@ # Procedure to run nFAPI in 5G NR -## Conributed by 5G Testbed IISc +## Contributed by 5G Testbed IISc ### Developers: Gokul S, Mahesh A, Aniq U R From 80305493422dbe75adb922eb1e8beb0de91ef8d6 Mon Sep 17 00:00:00 2001 From: Mahesh Date: Wed, 11 Aug 2021 16:15:49 +0530 Subject: [PATCH 135/185] phy-sim build error fix --- nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c | 2 -- openair1/SIMULATION/NR_PHY/dlsim.c | 7 ++++++- openair1/SIMULATION/NR_PHY/nr_dummy_functions.c | 6 ++++++ .../SIMULATION/NR_PHY/nr_dummy_functions_prach.c | 12 +++++++++--- openair1/SIMULATION/NR_PHY/prachsim.c | 5 +++++ openair1/SIMULATION/NR_PHY/ulsim.c | 5 +++++ .../NR_UE_PHY/unit_tests/src/dummy_functions.c | 5 +++++ 7 files changed, 36 insertions(+), 6 deletions(-) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 4878150330..8cebf2b468 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -185,8 +185,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) } selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); - - nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; if(selectRetval == 0) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b597425ddf..3f3db53e3e 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -227,12 +227,17 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, void processSlotTX(void *arg) {} -//nFAPI P7 dummy functions +//nFAPI P7 dummy functions to avoid linking errors int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index 24ed8a930c..e9588ea49c 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -8,6 +8,12 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } + int32_t get_uldl_offset(int nr_bandP) { return(0); } NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);} nfapi_mode_t nfapi_mod; diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c index a930c96a75..d02f3fa493 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c @@ -3,9 +3,15 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { re int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } - int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } - int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } - int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } + int32_t get_uldl_offset(int nr_bandP) { return(0); } NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);} int dummy_nr_ue_dl_indication(nr_downlink_indication_t *dl_info) { return(0); } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 93bed5514f..d9542a37ad 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -81,6 +81,11 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } void rrc_data_ind( diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 62f4420e75..705b801d7a 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -213,6 +213,11 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } int nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out) diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c index 4d17fe723c..b8a5c7a780 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c @@ -146,6 +146,11 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } +int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) { return(0); } +int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) { return(0); } +int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) { return(0); } +int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) { return(0); } +int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } From 146f8e6e0db5a91ae2279b71aa1195da97893b88 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 12 Aug 2021 12:17:59 +0200 Subject: [PATCH 136/185] doc(docker): added tutorial for deploying 5G SA RF sim Signed-off-by: Raphael Defosseux --- .../yaml_files/4g_rfsimulator/README.md | 5 +- .../yaml_files/5g_rfsimulator/README.md | 396 ++++++++++++++++++ .../5g_rfsimulator/oai-end-to-end.jpg | Bin 0 -> 56238 bytes 3 files changed, 400 insertions(+), 1 deletion(-) create mode 100644 ci-scripts/yaml_files/5g_rfsimulator/README.md create mode 100644 ci-scripts/yaml_files/5g_rfsimulator/oai-end-to-end.jpg diff --git a/ci-scripts/yaml_files/4g_rfsimulator/README.md b/ci-scripts/yaml_files/4g_rfsimulator/README.md index a677c642f4..b2a7f8e30c 100644 --- a/ci-scripts/yaml_files/4g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/4g_rfsimulator/README.md @@ -7,7 +7,7 @@ - OAI Full Stack RF simulation with containers + OAI Full Stack 4G-LTE RF simulation with containers @@ -81,11 +81,14 @@ How to build the Traffic-Generator image is explained [here](https://github.com/ **Just `docker-compose up -d` WILL NOT WORK!** +All the following commands **SHALL** be run from the `ci-scripts/yaml_files/4g_rfsimulator` folder. + ## 2.1. Deploy and Configure Cassandra Database ## It is very crutial that the Cassandra DB is fully configured before you do anything else! ```bash +$ cd ci-scripts/yaml_files/4g_rfsimulator $ docker-compose up -d db_init Creating network "rfsim4g-oai-private-net" with the default driver Creating network "rfsim4g-oai-public-net" with the default driver diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md new file mode 100644 index 0000000000..807f1b47c5 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -0,0 +1,396 @@ + + + + + +
+ + + + + + OAI Full Stack 5G-NR RF simulation with containers +
+ +This page is only valid for an `Ubuntu18` host. + +**TABLE OF CONTENTS** + +1. [Retrieving the images on Docker-Hub](#1-retrieving-the-images-on-docker-hub) +2. [Deploy containers](#2-deploy-containers) + 1. [Deploy OAI 5G Core Network](#21-deploy-oai-5g-core-network) + 2. [Deploy OAI gNB in RF simulator mode and in Standalone Mode](#22-deploy-oai-gnb-in-rf-simulator-mode-and-in-standalone-mode) + 3. [Deploy OAI NR-UE in RF simulator mode and in Standalone Mode](#23-deploy-oai-nr-ue-in-rf-simulator-mode-and-in-standalone-mode) +3. [Check traffic](#3-check-traffic) + 1. [Check your Internet connectivity](#31-check-your-internet-connectivity) + 2. [Start the iperf server inside the NR-UE container](#32-start-the-iperf-server-inside-the-nr-ue-container) + 3. [Start the iperf client inside the ext-dn container](#33-start-the-iperf-client-inside-the-ext-dn-container) +4. [Un-deployment](#4-un-deployment) + +# 1. Retrieving the images on Docker-Hub # + +Currently the images are hosted under the user account `rdefosseoai`. + +This may change in the future. + +Once again you may need to log on [docker-hub](https://hub.docker.com/) if your organization has reached pulling limit as `anonymous`. + +```bash +$ docker login +Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. +Username: +Password: +``` + +Now pull images. + +```bash +$ docker pull mysql:5.7 +$ docker pull rdefosseoai/oai-amf:latest +$ docker pull rdefosseoai/oai-nrf:latest +$ docker pull rdefosseoai/oai-smf:latest +$ docker pull rdefosseoai/oai-spgwu-tiny:latest + +$ docker pull rdefosseoai/oai-gnb:develop +$ docker pull rdefosseoai/oai-nr-ue:develop +``` + +And **re-tag** them for tutorials' docker-compose file to work. + +```bash +$ docker image tag rdefosseoai/oai-amf:latest oai-amf:latest +$ docker image tag rdefosseoai/oai-nrf:latest oai-nrf:latest +$ docker image tag rdefosseoai/oai-smf:latest oai-smf:latest +$ docker image tag rdefosseoai/oai-spgwu-tiny:latest oai-spgwu-tiny:latest + +$ docker image tag rdefosseoai/oai-gnb:develop oai-gnb:develop +$ docker image tag rdefosseoai/oai-nr-ue:develop oai-nr-ue:develop +``` + +```bash +$ docker logout +``` + +# 2. Deploy containers # + +![Deployment](./oai-end-to-end.jpg) + +**CAUTION: this SHALL be done in multiple steps.** + +**Just `docker-compose up -d` WILL NOT WORK!** + +All the following commands **SHALL** be run from the `ci-scripts/yaml_files/5g_rfsimulator` folder. + +## 2.1. Deploy OAI 5G Core Network ## + +```bash +$ cd ci-scripts/yaml_files/5g_rfsimulator +$ docker-compose up -d mysql oai-nrf oai-amf oai-smf oai-spgwu oai-ext-dn +Creating network "rfsim5g-oai-public-net" with driver "bridge" +Creating network "rfsim5g-oai-traffic_net-net" with driver "bridge" +Creating rfsim5g-oai-nrf ... done +Creating rfsim5g-mysql ... done +Creating rfsim5g-oai-spgwu ... done +Creating rfsim5g-oai-amf ... done +Creating rfsim5g-oai-smf ... done +Creating rfsim5g-oai-ext-dn ... done +``` + +Wait for a bit. + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------- +rfsim5g-mysql docker-entrypoint.sh mysqld Up (healthy) 3306/tcp, 33060/tcp +rfsim5g-oai-amf /bin/bash /openair-amf/bin ... Up (healthy) 38412/sctp, 80/tcp, 9090/tcp +rfsim5g-oai-ext-dn /bin/bash -c apt update; ... Up (healthy) +rfsim5g-oai-nrf /bin/bash /openair-nrf/bin ... Up (healthy) 80/tcp, 9090/tcp +rfsim5g-oai-smf /bin/bash -c /openair-smf/ ... Up (healthy) 80/tcp, 8805/udp, 9090/tcp +rfsim5g-oai-spgwu /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +``` + +At this point, you can prepare a capture on the newly-created public docker bridges: + +```bash +$ ifconfig +... +rfsim5g-public: flags=4163 mtu 1500 + inet 192.168.71.129 netmask 255.255.255.192 broadcast 192.168.71.191 + inet6 fe80::42:c4ff:fe2b:3d38 prefixlen 64 scopeid 0x20 + ether 02:42:c4:2b:3d:38 txqueuelen 0 (Ethernet) + RX packets 4 bytes 112 (112.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 7 bytes 626 (626.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +rfsim5g-traffic: flags=4163 mtu 1500 + inet 192.168.72.129 netmask 255.255.255.192 broadcast 192.168.72.191 + inet6 fe80::42:b5ff:fed3:e732 prefixlen 64 scopeid 0x20 + ether 02:42:b5:d3:e7:32 txqueuelen 0 (Ethernet) + RX packets 2652 bytes 142335 (142.3 KB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 3999 bytes 23367972 (23.3 MB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +... +``` + +## 2.2. Deploy OAI gNB in RF simulator mode and in Standalone Mode ## + +```bash +$ docker-compose up -d oai-gnb +rfsim5g-oai-nrf is up-to-date +rfsim5g-oai-spgwu is up-to-date +rfsim5g-oai-ext-dn is up-to-date +Creating rfsim5g-oai-gnb ... done +``` + +Wait for a bit. + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------- +rfsim5g-mysql docker-entrypoint.sh mysqld Up (healthy) 3306/tcp, 33060/tcp +rfsim5g-oai-amf /bin/bash /openair-amf/bin ... Up (healthy) 38412/sctp, 80/tcp, 9090/tcp +rfsim5g-oai-ext-dn /bin/bash -c apt update; ... Up (healthy) +rfsim5g-oai-gnb /opt/oai-gnb/bin/entrypoin ... Up (healthy) +rfsim5g-oai-nrf /bin/bash /openair-nrf/bin ... Up (healthy) 80/tcp, 9090/tcp +rfsim5g-oai-smf /bin/bash -c /openair-smf/ ... Up (healthy) 80/tcp, 8805/udp, 9090/tcp +rfsim5g-oai-spgwu /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +``` + +## 2.3. Deploy OAI NR-UE in RF simulator mode and in Standalone Mode ## + +```bash +$ docker-compose up -d oai-nr-ue +rfsim5g-mysql is up-to-date +rfsim5g-oai-nrf is up-to-date +rfsim5g-oai-spgwu is up-to-date +rfsim5g-oai-ext-dn is up-to-date +rfsim5g-oai-gnb is up-to-date +Creating rfsim5g-oai-nr-ue ... done +``` + +Wait for a bit. + +```bash +$ docker-compose ps -a + Name Command State Ports +------------------------------------------------------------------------------------------------- +rfsim5g-mysql docker-entrypoint.sh mysqld Up (healthy) 3306/tcp, 33060/tcp +rfsim5g-oai-amf /bin/bash /openair-amf/bin ... Up (healthy) 38412/sctp, 80/tcp, 9090/tcp +rfsim5g-oai-ext-dn /bin/bash -c apt update; ... Up (healthy) +rfsim5g-oai-gnb /opt/oai-gnb/bin/entrypoin ... Up (healthy) +rfsim5g-oai-nr-ue /opt/oai-nr-ue/bin/entrypo ... Up (healthy) +rfsim5g-oai-nrf /bin/bash /openair-nrf/bin ... Up (healthy) 80/tcp, 9090/tcp +rfsim5g-oai-smf /bin/bash -c /openair-smf/ ... Up (healthy) 80/tcp, 8805/udp, 9090/tcp +rfsim5g-oai-spgwu /openair-spgwu-tiny/bin/en ... Up (healthy) 2152/udp, 8805/udp +``` + +Making sure the OAI UE is connected: + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash +root@bb4d400a832d:/opt/oai-nr-ue# ifconfig +eth0: flags=4163 mtu 1500 + inet 192.168.71.137 netmask 255.255.255.192 broadcast 192.168.71.191 + ether 02:42:c0:a8:47:89 txqueuelen 0 (Ethernet) + RX packets 224259 bytes 5821372018 (5.8 GB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 235916 bytes 7848786376 (7.8 GB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +lo: flags=73 mtu 65536 + inet 127.0.0.1 netmask 255.0.0.0 + loop txqueuelen 1000 (Local Loopback) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +oaitun_ue1: flags=4305 mtu 1500 + inet 12.1.1.2 netmask 255.255.255.0 destination 12.1.1.2 + unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +``` + +**CAUTION: THESE NEXT FEW COMMANDS ARE A HACK. RAN developers SHALL FIX THIS!** + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash + +# Check the current routes + +root@bb4d400a832d:/opt/oai-nr-ue# ip route +default via 192.168.71.129 dev eth0 +12.1.1.0/24 dev oaitun_ue1 proto kernel scope link src 12.1.1.2 +192.168.71.128/26 dev eth0 proto kernel scope link src 192.168.71.137 + +# Remove the default and PDN routes + +root@bb4d400a832d:/opt/oai-nr-ue# ip route del default +root@bb4d400a832d:/opt/oai-nr-ue# ip route del 12.1.1.0/24 + +# Force the default route through oaitun_ue1 tunnel + +root@bb4d400a832d:/opt/oai-nr-ue# ip route add default via 12.1.1.2 dev oaitun_ue1 + +# Check the new routes + +root@bb4d400a832d:/opt/oai-nr-ue# ip route +default via 12.1.1.2 dev oaitun_ue1 +192.168.71.128/26 dev eth0 proto kernel scope link src 192.168.71.137 +``` + +# 3. Check traffic # + +## 3.1. Check your Internet connectivity ## + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash +root@bb4d400a832d:/opt/oai-nr-ue# ping -I oaitun_ue1 -c 10 www.lemonde.fr +PING s2.shared.global.fastly.net (151.101.122.217) from 12.1.1.2 oaitun_ue1: 56(84) bytes of data. +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=1 ttl=53 time=64.5 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=2 ttl=53 time=37.0 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=3 ttl=53 time=43.2 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=4 ttl=53 time=43.2 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=5 ttl=53 time=54.3 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=6 ttl=53 time=24.0 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=7 ttl=53 time=32.5 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=8 ttl=53 time=37.0 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=9 ttl=53 time=41.2 ms +64 bytes from 151.101.122.217 (151.101.122.217): icmp_seq=10 ttl=53 time=50.3 ms + +--- s2.shared.global.fastly.net ping statistics --- +10 packets transmitted, 10 received, 0% packet loss, time 9011ms +rtt min/avg/max/mdev = 24.035/42.765/64.557/10.904 ms +``` + +If it does not work, certainly you need to modify the DNS values in the docker-compose. + +But you can also check with the `ext-dn` container (IP address is `192.168.72.135` in docker-compose) + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash +root@bb4d400a832d# ping -I oaitun_ue1 -c 2 192.168.72.135 +PING 192.168.72.135 (192.168.72.135) from 12.1.1.2 oaitun_ue1: 56(84) bytes of data. +64 bytes from 192.168.72.135: icmp_seq=1 ttl=63 time=10.9 ms +64 bytes from 192.168.72.135: icmp_seq=2 ttl=63 time=16.5 ms + +--- 192.168.72.135 ping statistics --- +2 packets transmitted, 2 received, 0% packet loss, time 1001ms +rtt min/avg/max/mdev = 10.939/13.747/16.556/2.810 ms +``` + +Let now try to check UDP traffic in Downlink. + +You will need 2 terminals: one in the NR-UE container, one in the ext-dn container. + +## 3.2. Start the `iperf` server inside the NR-UE container ## + +```bash +$ docker exec -it rfsim5g-oai-nr-ue /bin/bash +root@bb4d400a832d:/opt/oai-nr-ue# iperf -B 12.1.1.2 -u -i 1 -s +------------------------------------------------------------ +Server listening on UDP port 5001 +Binding to local address 12.1.1.2 +Receiving 1470 byte datagrams +UDP buffer size: 208 KByte (default) +------------------------------------------------------------ +``` + +## 3.3. Start the `iperf` client inside the ext-dn container ## + +```bash +$ docker exec -it rfsim5g-oai-ext-dn /bin/bash +root@f239e31a0bd0:/# iperf -c 12.1.1.2 -u -i 1 -t 20 -b 500K +------------------------------------------------------------ +Client connecting to 12.1.1.2, UDP port 5001 +Sending 1470 byte datagrams, IPG target: 22968.75 us (kalman adjust) +UDP buffer size: 208 KByte (default) +------------------------------------------------------------ +[ 3] local 192.168.72.135 port 58800 connected with 12.1.1.2 port 5001 +[ ID] Interval Transfer Bandwidth +[ 3] 0.0- 1.0 sec 64.6 KBytes 529 Kbits/sec +[ 3] 1.0- 2.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 2.0- 3.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 3.0- 4.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 4.0- 5.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 5.0- 6.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 6.0- 7.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 7.0- 8.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 8.0- 9.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 9.0-10.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 10.0-11.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 11.0-12.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 12.0-13.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 13.0-14.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 14.0-15.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 15.0-16.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 16.0-17.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 17.0-18.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 18.0-19.0 sec 63.2 KBytes 517 Kbits/sec +[ 3] 19.0-20.0 sec 61.7 KBytes 506 Kbits/sec +[ 3] 0.0-20.0 sec 1.22 MBytes 512 Kbits/sec +[ 3] Sent 872 datagrams +[ 3] Server Report: +[ 3] 0.0-20.0 sec 1.22 MBytes 510 Kbits/sec 0.000 ms 3/ 872 (0%) +``` + +Back on your NR-UE terminal you shall see: + +```bash +[ 3] local 12.1.1.2 port 5001 connected with 192.168.72.135 port 58800 +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams +[ 3] 0.0- 1.0 sec 63.2 KBytes 517 Kbits/sec 1.113 ms 0/ 44 (0%) +[ 3] 1.0- 2.0 sec 61.7 KBytes 506 Kbits/sec 1.466 ms 0/ 43 (0%) +[ 3] 2.0- 3.0 sec 63.2 KBytes 517 Kbits/sec 1.770 ms 0/ 44 (0%) +[ 3] 3.0- 4.0 sec 61.7 KBytes 506 Kbits/sec 1.378 ms 0/ 43 (0%) +[ 3] 4.0- 5.0 sec 63.2 KBytes 517 Kbits/sec 1.614 ms 0/ 44 (0%) +[ 3] 5.0- 6.0 sec 63.2 KBytes 517 Kbits/sec 1.427 ms 0/ 44 (0%) +[ 3] 6.0- 7.0 sec 60.3 KBytes 494 Kbits/sec 1.507 ms 1/ 43 (2.3%) +[ 3] 7.0- 8.0 sec 63.2 KBytes 517 Kbits/sec 1.409 ms 0/ 44 (0%) +[ 3] 8.0- 9.0 sec 61.7 KBytes 506 Kbits/sec 1.525 ms 0/ 43 (0%) +[ 3] 9.0-10.0 sec 63.2 KBytes 517 Kbits/sec 1.393 ms 0/ 44 (0%) +[ 3] 10.0-11.0 sec 61.7 KBytes 506 Kbits/sec 1.377 ms 0/ 43 (0%) +[ 3] 11.0-12.0 sec 63.2 KBytes 517 Kbits/sec 1.501 ms 0/ 44 (0%) +[ 3] 12.0-13.0 sec 61.7 KBytes 506 Kbits/sec 1.788 ms 0/ 43 (0%) +[ 3] 13.0-14.0 sec 63.2 KBytes 517 Kbits/sec 1.466 ms 0/ 44 (0%) +[ 3] 14.0-15.0 sec 61.7 KBytes 506 Kbits/sec 1.381 ms 0/ 43 (0%) +[ 3] 15.0-16.0 sec 61.7 KBytes 506 Kbits/sec 1.417 ms 1/ 44 (2.3%) +[ 3] 16.0-17.0 sec 61.7 KBytes 506 Kbits/sec 1.569 ms 0/ 43 (0%) +[ 3] 17.0-18.0 sec 63.2 KBytes 517 Kbits/sec 1.492 ms 1/ 45 (2.2%) +[ 3] 18.0-19.0 sec 61.7 KBytes 506 Kbits/sec 1.376 ms 0/ 43 (0%) +[ 3] 19.0-20.0 sec 61.7 KBytes 506 Kbits/sec 1.589 ms 0/ 43 (0%) +[ 3] 0.0-20.0 sec 1.22 MBytes 510 Kbits/sec 1.551 ms 3/ 872 (0.34%) +``` + +The `500 Kbits/sec` value may change depending on your CPU power! + +# 4. Un-deployment # + +```bash +$ docker-compose down +Stopping rfsim5g-oai-nr-ue ... done +Stopping rfsim5g-oai-gnb ... done +Stopping rfsim5g-oai-ext-dn ... done +Stopping rfsim5g-oai-smf ... done +Stopping rfsim5g-oai-amf ... done +Stopping rfsim5g-oai-spgwu ... done +Stopping rfsim5g-oai-nrf ... done +Stopping rfsim5g-mysql ... done +Removing rfsim5g-oai-nr-ue ... done +Removing rfsim5g-oai-gnb ... done +Removing rfsim5g-oai-ext-dn ... done +Removing rfsim5g-oai-smf ... done +Removing rfsim5g-oai-amf ... done +Removing rfsim5g-oai-spgwu ... done +Removing rfsim5g-oai-nrf ... done +Removing rfsim5g-mysql ... done +Removing network rfsim5g-oai-public-net +Removing network rfsim5g-oai-traffic_net-net +``` diff --git a/ci-scripts/yaml_files/5g_rfsimulator/oai-end-to-end.jpg b/ci-scripts/yaml_files/5g_rfsimulator/oai-end-to-end.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f454a016f624196c87baa431f5974d148ec677be GIT binary patch literal 56238 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 yfY{p};9y!mWx Date: Fri, 13 Aug 2021 10:29:51 +0200 Subject: [PATCH 137/185] feat(ci): Q&D adding of 5G RF sim on container/docker-compose Signed-off-by: Raphael Defosseux --- ci-scripts/cls_containerize.py | 316 +++++++++++++++++- ci-scripts/main.py | 61 +++- ci-scripts/xml_class_list.yml | 4 + ci-scripts/xml_files/container_5g_rfsim.xml | 103 ++++++ .../xml_files/container_5g_rfsim_down.xml | 38 +++ .../5g_rfsimulator/docker-compose.yaml | 2 +- 6 files changed, 520 insertions(+), 4 deletions(-) create mode 100644 ci-scripts/xml_files/container_5g_rfsim.xml create mode 100644 ci-scripts/xml_files/container_5g_rfsim_down.xml diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index f32e8b3864..63b707aa74 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -36,6 +36,7 @@ import re # reg import logging import os import shutil +import subprocess import time from multiprocessing import Process, Lock, SimpleQueue from zipfile import ZipFile @@ -76,6 +77,9 @@ class Containerize(): self.eNB_instance = 0 self.eNB_serverId = ['', '', ''] self.yamlPath = ['', '', ''] + self.services = ['', '', ''] + self.nb_healthy = [0, 0, 0] + self.exitStatus = 0 self.eNB_logFile = ['', '', ''] self.testCase_id = '' @@ -89,6 +93,14 @@ class Containerize(): self.allImagesSize = {} self.collectInfo = {} + self.pingContName = '' + self.pingOptions = '' + self.pingLossThreshold = '' + self.svrContName = '' + self.svrOptions = '' + self.cliContName = '' + self.cliOptions = '' + #----------------------------------------------------------- # Container management functions #----------------------------------------------------------- @@ -476,7 +488,6 @@ class Containerize(): HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) def UndeployObject(self, HTML, RAN): - logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m') if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName @@ -529,4 +540,307 @@ class Containerize(): HTML.CreateHtmlTestRow(RAN.runtime_stats, 'KO', logStatus) else: HTML.CreateHtmlTestRow(RAN.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) + logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m') + def DeployGenObject(self, HTML): + self.exitStatus = 0 + logging.info('\u001B[1m Checking Services to deploy\u001B[0m') + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose config --services' + logging.debug(cmd) + try: + listServices = subprocess.check_output(cmd, shell=True, universal_newlines=True) + except Exception as e: + self.exitStatus = 1 + HTML.CreateHtmlTestRow('SVC not Found', 'KO', CONST.ALL_PROCESSES_OK) + return + for reqSvc in self.services[0].split(' '): + res = re.search(reqSvc, listServices) + if res is None: + logging.error(reqSvc + ' not found in specified docker-compose') + self.exitStatus = 1 + if (self.exitStatus == 1): + HTML.CreateHtmlTestRow('SVC not Found', 'KO', CONST.ALL_PROCESSES_OK) + return + + if (self.ranAllowMerge): + cmd = 'cd ' + self.yamlPath[0] + ' && sed -e "s@develop@ci-temp@" docker-compose.y*ml > docker-compose-ci.yml' + else: + cmd = 'cd ' + self.yamlPath[0] + ' && sed -e "s@develop@develop@" docker-compose.y*ml > docker-compose-ci.yml' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml up -d ' + self.services[0] + logging.debug(cmd) + try: + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=30) + except Exception as e: + self.exitStatus = 1 + logging.error('Could not deploy') + HTML.CreateHtmlTestRow('Could not deploy', 'KO', CONST.ALL_PROCESSES_OK) + return + + logging.info('\u001B[1m Checking if all deployed healthy\u001B[0m') + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml ps -a' + count = 0 + healthy = 0 + while (count < 10): + count += 1 + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + healthy = 0 + for state in deployStatus.split('\n'): + res = re.search('Up \(healthy\)', state) + if res is not None: + healthy += 1 + if healthy == self.nb_healthy[0]: + count = 100 + else: + time.sleep(10) + + # HACK TO REMOVE LATER WHEN FIX + res = re.search('oai-nr-ue', self.services[0]) + if res is not None: + cmd = 'docker exec rfsim5g-oai-nr-ue /bin/bash -c "ip route del default"' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + cmd = 'docker exec rfsim5g-oai-nr-ue /bin/bash -c "ip route del 12.1.1.0/24"' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + cmd = 'docker exec rfsim5g-oai-nr-ue /bin/bash -c "ip route add default via 12.1.1.2 dev oaitun_ue1"' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + # END OF HACK TO REMOVE LATER WHEN FIX + + if count == 100 and healthy == self.nb_healthy[0]: + HTML.CreateHtmlTestRow('n/a', 'OK', CONST.ALL_PROCESSES_OK) + logging.info('\u001B[1m Deploying OAI Object(s) PASS\u001B[0m') + else: + self.exitStatus = 1 + HTML.CreateHtmlTestRow('Could not deploy in time', 'KO', CONST.ALL_PROCESSES_OK) + logging.error('\u001B[1m Deploying OAI Object(s) FAILED\u001B[0m') + + def UndeployGenObject(self, HTML): + self.exitStatus = 0 + + if (self.ranAllowMerge): + cmd = 'cd ' + self.yamlPath[0] + ' && sed -e "s@develop@ci-temp@" docker-compose.y*ml > docker-compose-ci.yml' + else: + cmd = 'cd ' + self.yamlPath[0] + ' && sed -e "s@develop@develop@" docker-compose.y*ml > docker-compose-ci.yml' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + +# if the containers are running, recover the logs! + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml ps --all' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + anyLogs = False + for state in deployStatus.split('\n'): + res = re.search('Name|----------', state) + if res is not None: + continue + if len(state) == 0: + continue + res = re.search('^(?P[a-zA-Z0-9\-\_]+) ', state) + if res is not None: + anyLogs = True + cName = res.group('container_name') + cmd = 'cd ' + self.yamlPath[0] + ' && docker logs ' + cName + ' > ' + cName + '.log 2>&1' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + if anyLogs: + cmd = 'mkdir -p ../cmake_targets/log && mv ' + self.yamlPath[0] + '/*.log ../cmake_targets/log' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + + cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml down' + logging.debug(cmd) + try: + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100) + except Exception as e: + self.exitStatus = 1 + logging.error('Could not undeploy') + HTML.CreateHtmlTestRow('Could not undeploy', 'KO', CONST.ALL_PROCESSES_OK) + logging.error('\u001B[1m Undeploying OAI Object(s) FAILED\u001B[0m') + return + + HTML.CreateHtmlTestRow('n/a', 'OK', CONST.ALL_PROCESSES_OK) + logging.info('\u001B[1m Undeploying OAI Object(s) PASS\u001B[0m') + + def PingFromContainer(self, HTML): + self.exitStatus = 0 + cmd = 'mkdir -p ../cmake_targets/log' + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + + cmd = 'docker exec ' + self.pingContName + ' /bin/bash -c "ping ' + self.pingOptions + '" 2>&1 | tee ../cmake_targets/log/ping_' + HTML.testCase_id + '.log' + logging.debug(cmd) + deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100) + + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', deployStatus) + if result is None: + self.PingExit(HTML, False, 'Packet Loss Not Found') + return + + packetloss = result.group('packetloss') + if float(packetloss) == 100: + self.PingExit(HTML, False, 'Packet Loss is 100%') + return + + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', deployStatus) + if result is None: + self.PingExit(HTML, False, 'Ping RTT_Min RTT_Avg RTT_Max Not Found!') + return + + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + + message = 'ping result\n' + message += ' ' + pal_msg + '\n' + message += ' ' + min_msg + '\n' + message += ' ' + avg_msg + '\n' + message += ' ' + max_msg + '\n' + packetLossOK = True + if float(packetloss) > float(self.pingLossThreshold): + message += '\nPacket Loss too high' + packetLossOK = False + elif float(packetloss) > 0: + message += '\nPacket Loss is not 0%' + self.PingExit(HTML, packetLossOK, message) + + if packetLossOK: + logging.debug('\u001B[1;37;44m ping result \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + logging.info('\u001B[1m Ping Test PASS\u001B[0m') + + def PingExit(self, HTML, status, message): + html_queue = SimpleQueue() + html_cell = '

UE\n' + message + '
' + html_queue.put(html_cell) + if status: + HTML.CreateHtmlTestRowQueue(self.pingOptions, 'OK', 1, html_queue) + else: + self.exitStatus = 1 + logging.error('\u001B[1;37;41m ' + message + ' \u001B[0m') + HTML.CreateHtmlTestRowQueue(self.pingOptions, 'KO', 1, html_queue) + + def IperfFromContainer(self, HTML): + self.exitStatus = 0 + + cmd = 'mkdir -p ../cmake_targets/log' + logStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + + # Start the server process + cmd = 'docker exec -d ' + self.svrContName + ' /bin/bash -c "nohup iperf ' + self.svrOptions + ' > /tmp/iperf_server.log 2>&1"' + logging.debug(cmd) + serverStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + time.sleep(5) + + # Start the client process + cmd = 'docker exec ' + self.cliContName + ' /bin/bash -c "iperf ' + self.cliOptions + '" 2>&1 | tee ../cmake_targets/log/iperf_client_' + HTML.testCase_id + '.log' + logging.debug(cmd) + clientStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=100) + + # Stop the server process + cmd = 'docker exec ' + self.svrContName + ' /bin/bash -c "pkill iperf"' + logging.debug(cmd) + serverStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + time.sleep(5) + cmd = 'docker cp ' + self.svrContName + ':/tmp/iperf_server.log ../cmake_targets/log/iperf_server_' + HTML.testCase_id + '.log' + logging.debug(cmd) + serverStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) + + # Analyze client output + result = re.search('Server Report:', clientStatus) + if result is None: + result = re.search('read failed: Connection refused', clientStatus) + if result is not None: + message = 'Could not connect to iperf server!' + else: + message = 'Server Report and Connection refused Not Found!' + self.IperfExit(HTML, False, message) + return + + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', self.cliOptions) + if result is not None: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', self.cliOptions) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', self.cliOptions) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + + reportLine = None + reportLineFound = False + for iLine in clientStatus.split('\n'): + if reportLineFound: + reportLine = iLine + reportLineFound = False + res = re.search('Server Report:', iLine) + if res is not None: + reportLineFound = True + result = None + if reportLine is not None: + result = re.search('(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/ ..\d+) +(\((?P[0-9\.]+)%\))', reportLine) + iperfStatus = True + if result is not None: + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + jitter = result.group('jitter') + logging.debug('\u001B[1;37;44m iperf result \u001B[0m') + iperfStatus = True + msg = 'Req Bitrate : ' + req_bandwidth + '\n' + logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') + if bitrate is not None: + msg += 'Bitrate : ' + bitrate + '\n' + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) + if result is not None: + actual_bw = float(str(result.group('real_bw'))) + result = re.search('[0-9\.]+ K', bitrate) + if result is not None: + actual_bw = actual_bw * 1000 + result = re.search('[0-9\.]+ M', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000 + br_loss = 100 * actual_bw / req_bw + if br_loss < 90: + iperfStatus = False + bitperf = '%.2f ' % br_loss + msg += 'Bitrate Perf: ' + bitperf + '%\n' + logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') + if packetloss is not None: + msg += 'Packet Loss : ' + packetloss + '%\n' + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + if float(packetloss) > float(5): + msg += 'Packet Loss too high!\n' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + iperfStatus = False + if jitter is not None: + msg += 'Jitter : ' + jitter + '\n' + logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') + self.IperfExit(HTML, iperfStatus, msg) + else: + logging.error('problem?') + if iperfStatus: + logging.info('\u001B[1m Iperf Test PASS\u001B[0m') + + def IperfExit(self, HTML, status, message): + html_queue = SimpleQueue() + html_cell = '
UE\n' + message + '
' + html_queue.put(html_cell) + if status: + HTML.CreateHtmlTestRowQueue(self.cliOptions, 'OK', 1, html_queue) + else: + self.exitStatus = 1 + HTML.CreateHtmlTestRowQueue(self.cliOptions, 'KO', 1, html_queue) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 8a76d8dbce..f87fc1ed9c 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -372,6 +372,41 @@ def GetParametersFromXML(action): if (string_field is not None): CONTAINERS.yamlPath[CONTAINERS.eNB_instance] = string_field + elif action == 'DeployGenObject' or action == 'UndeployGenObject': + string_field=test.findtext('yaml_path') + if (string_field is not None): + CONTAINERS.yamlPath[0] = string_field + string_field=test.findtext('services') + if (string_field is not None): + CONTAINERS.services[0] = string_field + string_field=test.findtext('nb_healthy') + if (string_field is not None): + CONTAINERS.nb_healthy[0] = int(string_field) + + elif action == 'PingFromContainer': + string_field = test.findtext('container_name') + if (string_field is not None): + CONTAINERS.pingContName = string_field + string_field = test.findtext('options') + if (string_field is not None): + CONTAINERS.pingOptions = string_field + string_field = test.findtext('loss_threshold') + if (string_field is not None): + CONTAINERS.pingLossThreshold = string_field + + elif action == 'IperfFromContainer': + string_field = test.findtext('server_container_name') + if (string_field is not None): + CONTAINERS.svrContName = string_field + string_field = test.findtext('server_options') + if (string_field is not None): + CONTAINERS.svrOptions = string_field + string_field = test.findtext('client_container_name') + if (string_field is not None): + CONTAINERS.cliContName = string_field + string_field = test.findtext('client_options') + if (string_field is not None): + CONTAINERS.cliOptions = string_field else: # ie action == 'Run_PhySim': ldpc.runargs = test.findtext('physim_run_args') @@ -479,6 +514,8 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE): if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + if RAN.eNBIPAddress == 'none': + sys.exit(0) RAN.eNB_instance=0 RAN.eNB_serverId[0]='0' RAN.eNBSourceCodePath='/tmp/' @@ -514,11 +551,15 @@ elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): if (RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + if RAN.eNBIPAddress == 'none': + sys.exit(0) CiTestObj.LogCollectBuild(RAN) elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + if RAN.eNBIPAddress == 'none': + sys.exit(0) RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': @@ -802,7 +843,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif action == 'Build_PhySim': HTML=ldpc.Build_PhySim(HTML,CONST) if ldpc.exitStatus==1: - RAN.prematureExit = False + RAN.prematureExit = True elif action == 'Run_PhySim': HTML=ldpc.Run_PhySim(HTML,CONST,id) elif action == 'Build_Image': @@ -815,9 +856,25 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re SCA.CppCheckAnalysis(HTML) elif action == 'Deploy_Run_PhySim': PHYSIM.Deploy_PhySim(HTML, RAN) + elif action == 'DeployGenObject': + CONTAINERS.DeployGenObject(HTML) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True + elif action == 'UndeployGenObject': + CONTAINERS.UndeployGenObject(HTML) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True + elif action == 'PingFromContainer': + CONTAINERS.PingFromContainer(HTML) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True + elif action == 'IperfFromContainer': + CONTAINERS.IperfFromContainer(HTML) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True else: sys.exit('Invalid class (action) from xml') - if not RAN.prematureExit: + if RAN.prematureExit: if CiTestObj.testCase_id == CiTestObj.testMinStableId: logging.debug('Scenario has reached minimal stability point') CiTestObj.testStabilityPointReached = True diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index a43e5b79c0..d8e1b26a21 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -41,3 +41,7 @@ - Undeploy_Object - Cppcheck_Analysis - Deploy_Run_PhySim + - DeployGenObject + - UndeployGenObject + - PingFromContainer + - IperfFromContainer diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml new file mode 100644 index 0000000000..8847c11894 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -0,0 +1,103 @@ + + + rfsim-5gnr + Testing 5G NR RF sim in containers + wrench + + 000001 + 000002 + 000003 + 020001 + 020002 + 030001 + 030002 + 100001 + + + + + DeployGenObject + Deploy OAI 5G CoreNetwork + yaml_files/5g_rfsimulator + mysql oai-nrf oai-amf oai-smf oai-spgwu oai-ext-dn + 6 + + + + DeployGenObject + Deploy OAI 5G gNB RF sim SA + yaml_files/5g_rfsimulator + oai-gnb + 7 + + + + DeployGenObject + Deploy OAI 5G NR-UE RF sim SA + yaml_files/5g_rfsimulator + oai-nr-ue + 8 + + + + PingFromContainer + Ping ext-dn from NR-UE + rfsim5g-oai-nr-ue + -I oaitun_ue1 -c 20 192.168.72.135 + 5 + + + + PingFromContainer + Ping NR-UE from ext-dn + rfsim5g-oai-ext-dn + -c 20 12.1.1.2 + 5 + + + + IperfFromContainer + Iperf UDP Downlink + rfsim5g-oai-nr-ue + rfsim5g-oai-ext-dn + -B 12.1.1.2 -u -i 1 -s + -c 12.1.1.2 -u -i 1 -t 30 -b 400K + + + + IperfFromContainer + Iperf UDP Uplink + rfsim5g-oai-ext-dn + rfsim5g-oai-nr-ue + -u -i 1 -s + -B 12.1.1.2 -c 192.168.72.135 -u -i 1 -t 30 -b 20K + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator + + + diff --git a/ci-scripts/xml_files/container_5g_rfsim_down.xml b/ci-scripts/xml_files/container_5g_rfsim_down.xml new file mode 100644 index 0000000000..57b0f67a21 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_down.xml @@ -0,0 +1,38 @@ + + + rfsim-5gnr-down + CleanUp 5G RF + trash + + 100002 + + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator + + + diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index 02cf95bc59..5da7a353ab 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -206,7 +206,7 @@ services: privileged: true container_name: rfsim5g-oai-ext-dn entrypoint: /bin/bash -c \ - "apt update; apt install -y iptables iproute2 iperf iputils-ping;"\ + "apt update; apt install -y procps iptables iproute2 iperf iputils-ping;"\ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" depends_on: From 8f0218828fdfca7081601716d09a53ce9dd1eb5d Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 13 Aug 2021 10:45:20 +0200 Subject: [PATCH 138/185] feat(ci): triggering RF Sim pipeline from main pipeline Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-GitLab-Container | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index a4d7a4bf92..f4b99e7f92 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -198,6 +198,26 @@ pipeline { } } } + stage ("RF Simulators") { + when { expression {doMandatoryTests} } + steps { + script { + triggerSlaveJob ('RAN-RF-Sim-Test', 'Test-RF-Sim-Container') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-RF-Sim-Test') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } } } } From 8c91e719927dacad21efae9a7c0c9f5f420d8add Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 13 Aug 2021 10:57:42 +0200 Subject: [PATCH 139/185] feat(ci): adding artifacting on run logs Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-tmp-ran | 2 +- ci-scripts/args_parse.py | 3 +++ ci-scripts/main.py | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ci-scripts/Jenkinsfile-tmp-ran b/ci-scripts/Jenkinsfile-tmp-ran index 7d5307620f..a0d0f13871 100644 --- a/ci-scripts/Jenkinsfile-tmp-ran +++ b/ci-scripts/Jenkinsfile-tmp-ran @@ -369,7 +369,7 @@ pipeline { [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'] ]) { echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m' - sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}" + sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --BuildId=${env.BUILD_ID}" echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m' sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true" diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 0ed12bfc08..c0203a4c98 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -266,6 +266,9 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP,SCA,PHYSIM): elif re.match('^\-\-OCProjectName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-OCProjectName=(.+)$', myArgv, re.IGNORECASE) PHYSIM.OCProjectName = matchReg.group(1) + elif re.match('^\-\-BuildId=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-BuildId=(.+)$', myArgv, re.IGNORECASE) + RAN.BuildId = matchReg.group(1) else: HELP.GenericHelp(CONST.Version) sys.exit('Invalid Parameter: ' + myArgv) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index f87fc1ed9c..d66c0c6305 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -65,6 +65,7 @@ import xml.etree.ElementTree as ET import logging import datetime import signal +import subprocess from multiprocessing import Process, Lock, SimpleQueue logging.basicConfig( level=logging.DEBUG, @@ -559,6 +560,9 @@ elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') if RAN.eNBIPAddress == 'none': + cmd = 'zip -r enb.log.' + RAN.BuildId + '.zip cmake_targets/log' + logging.debug(cmd) + zipStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=60) sys.exit(0) RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): From 59413c184d6ae5b706e6a123d9b0c3aebf6085f3 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 13 Aug 2021 11:13:16 +0200 Subject: [PATCH 140/185] implementation of scheduling of msg3 retransmission at gnb --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 435 +++++++++++++----- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 1 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 10 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 10 + openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 5 +- 5 files changed, 339 insertions(+), 122 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 1d3f69d876..1500884251 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -545,7 +545,7 @@ void nr_initiate_ra_proc(module_id_t module_idP, if (ra->CellGroup && ra->CellGroup->spCellConfig && ra->CellGroup->spCellConfig->spCellConfigDedicated && ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList) { ra->bwp_id = 1; - bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; + bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1); @@ -653,33 +653,216 @@ void nr_initiate_ra_proc(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } - void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) - { - gNB_MAC_INST *mac = RC.nrmac[module_idP]; +void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - start_meas(&mac->schedule_ra); - for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &cc->ra[i]; - LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); - switch (ra->state) { - case Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra); - break; - case Msg4: - nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra); - break; - case WAIT_Msg4_ACK: - nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); - break; - default: - break; - } + gNB_MAC_INST *mac = RC.nrmac[module_idP]; + + start_meas(&mac->schedule_ra); + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &cc->ra[i]; + LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); + switch (ra->state) { + case Msg2: + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra); + break; + case Msg3_retransmission: + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra); + break; + case Msg4: + nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra); + break; + case WAIT_Msg4_ACK: + nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); + break; + default: + break; } } - stop_meas(&mac->schedule_ra); } + stop_meas(&mac->schedule_ra); +} + + +void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { + + gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + + NR_BWP_Uplink_t *ubwp = ra->CellGroup ? + ra->CellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1] : + NULL; + + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList= ubwp ? + ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList: + scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + + int mu = ubwp ? + ubwp->bwp_Common->genericParameters.subcarrierSpacing : + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + + uint8_t K2 = *pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2; + + const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]); + const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; + + if (is_xlsch_in_slot(RC.nrmac[module_idP]->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) { + // beam association for FR2 + int16_t *tdd_beam_association = nr_mac->tdd_beam_association; + if (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257) { + uint8_t tdd_period_slot = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if ((scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols > 0) || (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols > 0)) + tdd_period_slot++; + int num_tdd_period = sched_slot/tdd_period_slot; + if((tdd_beam_association[num_tdd_period]!=-1)&&(tdd_beam_association[num_tdd_period]!=ra->beam_id)) + return; // can't schedule retransmission in this slot + else + tdd_beam_association[num_tdd_period] = ra->beam_id; + } + + int bwpSize = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int bwpStart = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int scs = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + int fh = 0; + int startSymbolAndLength = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; + int mappingtype = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType; + + if (ra->CellGroup) { + AssertFatal(ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, + "downlinkBWP_ToAddModList has %d BWP!\n", ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); + int act_bwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int act_bwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength; + mappingtype = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->mappingType; + scs = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + fh = ubwp->bwp_Dedicated->pusch_Config->choice.setup->frequencyHopping ? 1 : 0; + if ((bwpStart < act_bwp_start) || (bwpSize > act_bwp_size)) + bwpStart = act_bwp_start; + } + uint16_t *vrb_map_UL = + &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; + + int rbStart = 0; + for (int i = 0; (i < ra->msg3_nb_rb) && (rbStart <= (bwpSize - ra->msg3_nb_rb)); i++) { + if (vrb_map_UL[rbStart + bwpStart + i]) { + rbStart += i; + i = 0; + } + } + if (rbStart > (bwpSize - ra->msg3_nb_rb)) { + // cannot find free vrb_map for msg3 retransmission in this slot + return; + } + + LOG_I(NR_MAC, "[gNB %d][RAPROC] Frame %d, Slot %d : CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n", + module_idP, frame, slot, CC_id, sched_frame, sched_slot); + + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][sched_slot]; + AssertFatal(future_ul_tti_req->SFN == sched_frame + && future_ul_tti_req->Slot == sched_slot, + "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + sched_frame, + sched_slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; + memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + + fill_msg3_pusch_pdu(pusch_pdu, scc, + startSymbolAndLength, + ra->rnti, scs, + bwpSize, bwpStart, + mappingtype, fh, + rbStart, ra->msg3_nb_rb); + future_ul_tti_req->n_pdus += 1; + + // generation of DCI 0_0 to schedule msg3 retransmission + NR_SearchSpace_t *ss = ra->ra_ss; + NR_BWP_Downlink_t *bwp = NULL; + NR_ControlResourceSet_t *coreset = NULL; + + if (ra->CellGroup && + ra->CellGroup->spCellConfig && + ra->CellGroup->spCellConfig->spCellConfigDedicated && + ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList && + ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]) + bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]; + + coreset = get_coreset(scc, bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); + AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg3 retransmission\n"); + + nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->UL_dci_req[CC_id]; + + const int coresetid = coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][ra->bwp_id][coresetid]; + if (!pdcch_pdu_rel15) { + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; + memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); + ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; + ul_dci_req->numPdus += 1; + nr_configure_pdcch(pdcch_pdu_rel15, ss, coreset, scc, bwp); + nr_mac->pdcch_pdu_idx[CC_id][ra->bwp_id][coresetid] = pdcch_pdu_rel15; + } + + uint8_t aggregation_level; + uint8_t nr_of_candidates; + find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss); + int CCEIndex = allocate_nr_CCEs(nr_mac, bwp, coreset, aggregation_level, 0, 0, nr_of_candidates); + if (CCEIndex < 0) { + LOG_E(NR_MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti); + return; + } + + // Fill PDCCH DL DCI PDU + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + pdcch_pdu_rel15->numDlDci++; + dci_pdu->RNTI = ra->rnti; + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + dci_pdu->AggregationLevel = aggregation_level; + dci_pdu->CceIndex = CCEIndex; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + + dci_pdu_rel15_t uldci_payload; + memset(&uldci_payload, 0, sizeof(uldci_payload)); + + config_uldci(ubwp, + scc, + pusch_pdu, + &uldci_payload, + NR_UL_DCI_FORMAT_0_0, + ra->Msg3_tda_id, + ra->msg3_TPC, + 0, // not used in format 0_0 + ra->bwp_id); + + fill_dci_pdu_rel15(scc, + ra->CellGroup, + dci_pdu, + &uldci_payload, + NR_UL_DCI_FORMAT_0_0, + NR_RNTI_TC, + pusch_pdu->bwp_size, + ra->bwp_id); + + // Mark the corresponding RBs as used + for (int rb = 0; rb < ra->msg3_nb_rb; rb++) { + vrb_map_UL[rbStart + bwpStart + rb] = 1; + } + + // reset state to wait msg3 + ra->state = WAIT_Msg3; + + } + +} void nr_get_Msg3alloc(module_id_t module_id, int CC_id, @@ -690,45 +873,45 @@ void nr_get_Msg3alloc(module_id_t module_id, NR_RA_t *ra, int16_t *tdd_beam_association) { - // msg3 is schedulend in mixed slot in the following TDD period + // msg3 is scheduled in mixed slot in the following TDD period - uint16_t msg3_nb_rb = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // sdu has 6 or 8 bytes + uint16_t msg3_nb_rb = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // sdu has 6 or 8 bytes - int mu = ubwp ? - ubwp->bwp_Common->genericParameters.subcarrierSpacing : - scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; - int StartSymbolIndex = 0; - int NrOfSymbols = 0; - int startSymbolAndLength = 0; - int temp_slot = 0; - ra->Msg3_tda_id = 16; // initialization to a value above limit + int mu = ubwp ? + ubwp->bwp_Common->genericParameters.subcarrierSpacing : + scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + int StartSymbolIndex = 0; + int NrOfSymbols = 0; + int startSymbolAndLength = 0; + int temp_slot = 0; + ra->Msg3_tda_id = 16; // initialization to a value above limit - NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList= ubwp ? - ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList: - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList= ubwp ? + ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList: + scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - uint8_t k2 = 0; - for (int i=0; ilist.count; i++) { - startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength; - SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols); - // we want to transmit in the uplink symbols of mixed slot - if (NrOfSymbols == scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols) { - k2 = *pusch_TimeDomainAllocationList->list.array[i]->k2; - temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213 - ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu]; - if (is_xlsch_in_slot(RC.nrmac[module_id]->ulsch_slot_bitmap[ra->Msg3_slot / 64], ra->Msg3_slot)) { - ra->Msg3_tda_id = i; - break; - } + uint8_t k2 = 0; + for (int i=0; ilist.count; i++) { + startSymbolAndLength = pusch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols); + // we want to transmit in the uplink symbols of mixed slot + if (NrOfSymbols == scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols) { + k2 = *pusch_TimeDomainAllocationList->list.array[i]->k2; + temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213 + ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu]; + if (is_xlsch_in_slot(RC.nrmac[module_id]->ulsch_slot_bitmap[ra->Msg3_slot / 64], ra->Msg3_slot)) { + ra->Msg3_tda_id = i; + break; } } + } - AssertFatal(ra->Msg3_tda_id<16,"Unable to find Msg3 time domain allocation in list\n"); + AssertFatal(ra->Msg3_tda_id<16,"Unable to find Msg3 time domain allocation in list\n"); - if (nr_slots_per_frame[mu]>temp_slot) - ra->Msg3_frame = current_frame; - else - ra->Msg3_frame = (current_frame + (temp_slot/nr_slots_per_frame[mu]))%1024; + if (nr_slots_per_frame[mu]>temp_slot) + ra->Msg3_frame = current_frame; + else + ra->Msg3_frame = (current_frame + (temp_slot/nr_slots_per_frame[mu]))%1024; // beam association for FR2 if (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0] >= 257) { @@ -750,7 +933,7 @@ void nr_get_Msg3alloc(module_id_t module_id, scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - /* search msg3_nb_rb free RBs */ + /* search msg3_nb_rb free RBs */ int rbSize = 0; int rbStart = 0; while (rbSize < msg3_nb_rb) { @@ -768,6 +951,74 @@ void nr_get_Msg3alloc(module_id_t module_id, ra->msg3_first_rb = rbStart; } + +void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_ServingCellConfigCommon_t *scc, + int startSymbolAndLength, + rnti_t rnti, int scs, + int bwp_size, int bwp_start, + int mappingtype, int fh, + int msg3_first_rb, int msg3_nb_rb) { + + + int start_symbol_index,nr_of_symbols; + SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols); + + pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + pusch_pdu->rnti = rnti; + pusch_pdu->handle = 0; + pusch_pdu->bwp_start = bwp_start; + pusch_pdu->bwp_size = bwp_size; + pusch_pdu->subcarrier_spacing = scs; + pusch_pdu->cyclic_prefix = 0; + pusch_pdu->mcs_index = 0; + pusch_pdu->mcs_table = 0; + pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table); + pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table); + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) + pusch_pdu->transform_precoding = 1; + else + pusch_pdu->transform_precoding = 0; + pusch_pdu->data_scrambling_id = *scc->physCellId; + pusch_pdu->nrOfLayers = 1; + pusch_pdu->ul_dmrs_symb_pos = get_l_prime(nr_of_symbols,mappingtype,pusch_dmrs_pos2,pusch_len1,start_symbol_index, scc->dmrs_TypeA_Position); + LOG_D(MAC, "MSG3 start_sym:%d NR Symb:%d mappingtype:%d , ul_dmrs_symb_pos:%x\n", start_symbol_index, nr_of_symbols, mappingtype, pusch_pdu->ul_dmrs_symb_pos); + pusch_pdu->dmrs_config_type = 0; + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. + pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0. + pusch_pdu->dmrs_ports = 1; // 6.2.2 in 38.214 only port 0 to be used + pusch_pdu->num_dmrs_cdm_grps_no_data = 2; // no data in dmrs symbols as in 6.2.2 in 38.214 + pusch_pdu->resource_alloc = 1; //type 1 + + pusch_pdu->rb_start = msg3_first_rb; + if (msg3_nb_rb > pusch_pdu->bwp_size) + AssertFatal(1==0,"MSG3 allocated number of RBs exceed the BWP size\n"); + else + pusch_pdu->rb_size = msg3_nb_rb; + pusch_pdu->vrb_to_prb_mapping = 0; + + pusch_pdu->frequency_hopping = fh; + //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] + pusch_pdu->uplink_frequency_shift_7p5khz = 0; + //Resource Allocation in time domain + pusch_pdu->start_symbol_index = start_symbol_index; + pusch_pdu->nr_of_symbols = nr_of_symbols; + //Optional Data only included if indicated in pduBitmap + pusch_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 + pusch_pdu->pusch_data.harq_process_id = 0; + pusch_pdu->pusch_data.new_data_indicator = 1; // new data + pusch_pdu->pusch_data.num_cb = 0; + pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, + pusch_pdu->target_code_rate, + pusch_pdu->rb_size, + pusch_pdu->nr_of_symbols, + 12, // nb dmrs set for no data in dmrs symbol + 0, //nb_rb_oh + 0, // to verify tb scaling + pusch_pdu->nrOfLayers)>>3; + +} + void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu) { gNB_MAC_INST *mac = RC.nrmac[module_idP]; @@ -790,7 +1041,7 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t vrb_map_UL[i + ra->msg3_first_rb] = 1; } - LOG_D(NR_MAC, "[gNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot); + LOG_D(NR_MAC, "[gNB %d][RAPROC] Frame %d, Slot %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot); nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][ra->Msg3_slot]; AssertFatal(future_ul_tti_req->SFN == ra->Msg3_frame @@ -804,7 +1055,7 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); - future_ul_tti_req->n_pdus += 1; + int ibwp_size = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); int ibwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); int abwp_size = ibwp_size; @@ -837,67 +1088,19 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t ra->msg3_round, ra->rnti); - int start_symbol_index,nr_of_symbols; - SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols); - - pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = ra->rnti; - pusch_pdu->handle = 0; - + int bwp_start; if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size)) - pusch_pdu->bwp_start = abwp_start; + bwp_start = abwp_start; else - pusch_pdu->bwp_start = ibwp_start; - pusch_pdu->bwp_size = ibwp_size; - pusch_pdu->subcarrier_spacing = scs; - pusch_pdu->cyclic_prefix = 0; - pusch_pdu->mcs_index = 0; - pusch_pdu->mcs_table = 0; - pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table); - pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table); - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - pusch_pdu->transform_precoding = 1; - else - pusch_pdu->transform_precoding = 0; - pusch_pdu->data_scrambling_id = *scc->physCellId; - pusch_pdu->nrOfLayers = 1; + bwp_start = ibwp_start; - pusch_pdu->ul_dmrs_symb_pos = get_l_prime(nr_of_symbols,mappingtype,pusch_dmrs_pos2,pusch_len1,start_symbol_index, scc->dmrs_TypeA_Position); - LOG_D(MAC, "MSG3 start_sym:%d NR Symb:%d mappingtype:%d , ul_dmrs_symb_pos:%x\n", start_symbol_index, nr_of_symbols, mappingtype, pusch_pdu->ul_dmrs_symb_pos); - - pusch_pdu->dmrs_config_type = 0; - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. - pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0. - pusch_pdu->dmrs_ports = 1; // 6.2.2 in 38.214 only port 0 to be used - pusch_pdu->num_dmrs_cdm_grps_no_data = 2; // no data in dmrs symbols as in 6.2.2 in 38.214 - pusch_pdu->resource_alloc = 1; //type 1 - //pusch_pdu->rb_start = ra->msg3_first_rb + ibwp_start - abwp_start; // as for 6.3.1.7 in 38.211 - pusch_pdu->rb_start = ra->msg3_first_rb; - if (ra->msg3_nb_rb > pusch_pdu->bwp_size) - AssertFatal(1==0,"MSG3 allocated number of RBs exceed the BWP size\n"); - else - pusch_pdu->rb_size = ra->msg3_nb_rb; - pusch_pdu->vrb_to_prb_mapping = 0; - - pusch_pdu->frequency_hopping = fh; - //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] - pusch_pdu->uplink_frequency_shift_7p5khz = 0; - //Resource Allocation in time domain - pusch_pdu->start_symbol_index = start_symbol_index; - pusch_pdu->nr_of_symbols = nr_of_symbols; - //Optional Data only included if indicated in pduBitmap - pusch_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 - pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 1; // new data - pusch_pdu->pusch_data.num_cb = 0; - pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, - pusch_pdu->target_code_rate, - pusch_pdu->rb_size, - pusch_pdu->nr_of_symbols, - 12, // nb dmrs set for no data in dmrs symbol - 0, //nb_rb_oh - 0, // to verify tb scaling - pusch_pdu->nrOfLayers = 1)>>3; + fill_msg3_pusch_pdu(pusch_pdu,scc, + startSymbolAndLength, + ra->rnti, scs, + ibwp_size, bwp_start, + mappingtype, fh, + ra->msg3_first_rb, ra->msg3_nb_rb); + future_ul_tti_req->n_pdus += 1; // calling function to fill rar message nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 546602427a..b595a89125 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -607,6 +607,7 @@ void config_uldci(const NR_BWP_Uplink_t *ubwp, uint8_t tpc, int n_ubwp, int bwp_id) { + const int bw = NRRIV2BW(ubwp ? ubwp->bwp_Common->genericParameters.locationAndBandwidth : scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index fbd8a4b5ca..d247aaa567 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -523,7 +523,6 @@ void handle_nr_ul_harq(module_id_t mod_id, } NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - int8_t harq_pid = sched_ctrl->feedback_ul_harq.head; while (crc_pdu->harq_id != harq_pid || harq_pid < 0) { LOG_W(NR_MAC, @@ -586,6 +585,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, const uint16_t timing_advance, const uint8_t ul_cqi, const uint16_t rssi){ + gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; NR_UE_info_t *UE_info = &gNB_mac->UE_info; @@ -784,9 +784,11 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, if (ra->state != WAIT_Msg3) continue; - LOG_W(NR_MAC, "Random Access %i failed at state %i (state is not WAIT_Msg3)\n", i, ra->state); - nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); - nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + if( (frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot)) + continue; + + LOG_W(NR_MAC, "Random Access %i failed at state %i (CRC did not pass)\n", i, ra->state); + ra->state = Msg3_retransmission; } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index c7e6f9c5fc..3af813e010 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -124,6 +124,8 @@ void nr_get_Msg3alloc(module_id_t module_id, NR_RA_t *ra, int16_t *tdd_beam_association); +void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); + /* \brief Function in gNB to fill RAR pdu when requested by PHY. @param ra Instance of RA resources of gNB @param dlsch_buffer Pointer to RAR input buffer @@ -134,6 +136,14 @@ void nr_fill_rar(uint8_t Mod_idP, uint8_t * dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); +void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_ServingCellConfigCommon_t *scc, + int startSymbolAndLength, + rnti_t rnti, int scs, + int bwp_size, int bwp_start, + int mappingtype, int fh, + int msg3_first_rb, int msg3_nb_rb); + void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index bd88c39306..e09df09c1e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -93,8 +93,9 @@ typedef enum { RA_IDLE = 0, Msg2 = 1, WAIT_Msg3 = 2, - Msg4 = 3, - WAIT_Msg4_ACK = 4 + Msg3_retransmission = 3, + Msg4 = 4, + WAIT_Msg4_ACK = 5 } RA_gNB_state_t; typedef struct NR_preamble_ue { From f2dd94d7c9acaf65016312e8e6dfb41981a6cc82 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 13 Aug 2021 11:48:14 +0200 Subject: [PATCH 141/185] fix in condition to call nr_ue_get_sdu --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 7c5cb27213..6520552670 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -954,7 +954,8 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in } else { if ((mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator || - mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id]==1) && ra->ra_state == RA_SUCCEEDED){ + mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id]==1) && + ((get_softmodem_params()->phy_test == 1) || (ra->ra_state == RA_SUCCEEDED))){ // Getting IP traffic to be transmitted data_existing = nr_ue_get_sdu(mod_id, From c70aa4c43a14aa0bdee525055194885308be1931 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 13 Aug 2021 14:21:50 +0200 Subject: [PATCH 142/185] fix(nr-ue): apply ip rules/route Signed-off-by: Raphael Defosseux --- ci-scripts/cls_containerize.py | 18 +-- ci-scripts/xml_files/container_4g_rfsim.xml | 130 ++++++++++++++++++ .../xml_files/container_4g_rfsim_down.xml | 38 +++++ ci-scripts/xml_files/container_5g_rfsim.xml | 1 + .../yaml_files/5g_rfsimulator/README.md | 28 ---- openair2/RRC/NAS/nas_config.c | 13 ++ 6 files changed, 185 insertions(+), 43 deletions(-) create mode 100644 ci-scripts/xml_files/container_4g_rfsim.xml create mode 100644 ci-scripts/xml_files/container_4g_rfsim_down.xml diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 63b707aa74..3e65f83e06 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -596,20 +596,6 @@ class Containerize(): else: time.sleep(10) - # HACK TO REMOVE LATER WHEN FIX - res = re.search('oai-nr-ue', self.services[0]) - if res is not None: - cmd = 'docker exec rfsim5g-oai-nr-ue /bin/bash -c "ip route del default"' - logging.debug(cmd) - deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) - cmd = 'docker exec rfsim5g-oai-nr-ue /bin/bash -c "ip route del 12.1.1.0/24"' - logging.debug(cmd) - deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) - cmd = 'docker exec rfsim5g-oai-nr-ue /bin/bash -c "ip route add default via 12.1.1.2 dev oaitun_ue1"' - logging.debug(cmd) - deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) - # END OF HACK TO REMOVE LATER WHEN FIX - if count == 100 and healthy == self.nb_healthy[0]: HTML.CreateHtmlTestRow('n/a', 'OK', CONST.ALL_PROCESSES_OK) logging.info('\u001B[1m Deploying OAI Object(s) PASS\u001B[0m') @@ -628,7 +614,7 @@ class Containerize(): logging.debug(cmd) subprocess.run(cmd, shell=True) -# if the containers are running, recover the logs! + # if the containers are running, recover the logs! cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml ps --all' logging.debug(cmd) deployStatus = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) @@ -831,7 +817,9 @@ class Containerize(): logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') self.IperfExit(HTML, iperfStatus, msg) else: + iperfStatus = False logging.error('problem?') + self.IperfExit(HTML, iperfStatus, 'problem?') if iperfStatus: logging.info('\u001B[1m Iperf Test PASS\u001B[0m') diff --git a/ci-scripts/xml_files/container_4g_rfsim.xml b/ci-scripts/xml_files/container_4g_rfsim.xml new file mode 100644 index 0000000000..f342c3f5ce --- /dev/null +++ b/ci-scripts/xml_files/container_4g_rfsim.xml @@ -0,0 +1,130 @@ + + + rfsim-4gnr + Testing 4G NR RF sim in containers + wrench + 4 + + 100011 + 000011 + 000001 + 000012 + 000002 + 000013 + 000001 + 000014 + 000002 + 020011 + 020012 + 030011 + 030012 + 100011 + + + + + DeployGenObject + Deploy Cassandra Database + yaml_files/4g_rfsimulator + cassandra db_init + 1 + + + + IdleSleep + Sleep + 30 + + + + IdleSleep + Sleep + 10 + + + + DeployGenObject + Deploy OAI 4G CoreNetwork + yaml_files/4g_rfsimulator + oai_hss oai_mme oai_spgwc oai_spgwu trf_gen + 6 + + + + DeployGenObject + Deploy OAI 4G eNB RF sim + yaml_files/4g_rfsimulator + enb + 7 + + + + DeployGenObject + Deploy OAI 4G NR-UE RF sim + yaml_files/4g_rfsimulator + oai_ue0 + 8 + + + + PingFromContainer + Ping Traffic-Gen from LTE-UE + rfsim4g-oai-lte-ue0 + -I oaitun_ue1 -c 20 192.168.61.11 + 5 + + + + PingFromContainer + Ping LTE-UE from Traffic-Gen + rfsim4g-trf-gen + -c 20 12.0.0.2 + 5 + + + + IperfFromContainer + Iperf UDP Downlink + rfsim4g-oai-lte-ue0 + rfsim4g-trf-gen + -B 12.0.0.2 -u -i 1 -s + -c 12.0.0.2 -u -i 1 -t 30 -b 4M + + + + IperfFromContainer + Iperf UDP Uplink + rfsim4g-trf-gen + rfsim4g-oai-lte-ue0 + -u -i 1 -s + -B 12.0.0.2 -c 192.168.61.11 -u -i 1 -t 30 -b 2M + + + + UndeployGenObject + Undeploy all OAI 4G stack + yaml_files/4g_rfsimulator + + + diff --git a/ci-scripts/xml_files/container_4g_rfsim_down.xml b/ci-scripts/xml_files/container_4g_rfsim_down.xml new file mode 100644 index 0000000000..cce2b32cf3 --- /dev/null +++ b/ci-scripts/xml_files/container_4g_rfsim_down.xml @@ -0,0 +1,38 @@ + + + rfsim-4gnr + Testing 4G NR RF sim in containers + wrench + + 100011 + + + + + UndeployGenObject + Undeploy all OAI 4G stack + yaml_files/4g_rfsimulator + + + diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index 8847c11894..660cd7cde8 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -25,6 +25,7 @@ Testing 5G NR RF sim in containers wrench + 100001 000001 000002 000003 diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md index 807f1b47c5..1351d6742b 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -218,34 +218,6 @@ oaitun_ue1: flags=4305 mtu 1500 TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ``` -**CAUTION: THESE NEXT FEW COMMANDS ARE A HACK. RAN developers SHALL FIX THIS!** - -```bash -$ docker exec -it rfsim5g-oai-nr-ue /bin/bash - -# Check the current routes - -root@bb4d400a832d:/opt/oai-nr-ue# ip route -default via 192.168.71.129 dev eth0 -12.1.1.0/24 dev oaitun_ue1 proto kernel scope link src 12.1.1.2 -192.168.71.128/26 dev eth0 proto kernel scope link src 192.168.71.137 - -# Remove the default and PDN routes - -root@bb4d400a832d:/opt/oai-nr-ue# ip route del default -root@bb4d400a832d:/opt/oai-nr-ue# ip route del 12.1.1.0/24 - -# Force the default route through oaitun_ue1 tunnel - -root@bb4d400a832d:/opt/oai-nr-ue# ip route add default via 12.1.1.2 dev oaitun_ue1 - -# Check the new routes - -root@bb4d400a832d:/opt/oai-nr-ue# ip route -default via 12.1.1.2 dev oaitun_ue1 -192.168.71.128/26 dev eth0 proto kernel scope link src 192.168.71.137 -``` - # 3. Check traffic # ## 3.1. Check your Internet connectivity ## diff --git a/openair2/RRC/NAS/nas_config.c b/openair2/RRC/NAS/nas_config.c index 2eb439b9e9..22a7ef2711 100644 --- a/openair2/RRC/NAS/nas_config.c +++ b/openair2/RRC/NAS/nas_config.c @@ -344,6 +344,19 @@ int nas_config(int interface_id, int thirdOctet, int fourthOctet, char *ifname) LOG_E(OIP,"Interface %s couldn't be configured (ip address %s, mask %s broadcast address %s)\n", interfaceName, ipAddress, netMask, broadcastAddress); + int res; + char command_line[500]; + res = sprintf(command_line, + "ip rule add from %s/32 table %d && " + "ip rule add to %s/32 table %d && " + "ip route add default dev %s%d table %d", + ipAddress, interface_id - 1 + 10000, + ipAddress, interface_id - 1 + 10000, + UE_NAS_USE_TUN ? "oaitun_ue" : "oip", + interface_id, interface_id - 1 + 10000); + + background_system(command_line); + return returnValue; } From 8060376fcd5859e59015926395f4ed87312a8f09 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 13 Aug 2021 15:56:49 +0200 Subject: [PATCH 143/185] fix compilation warning --- executables/nr-softmodem-common.h | 4 ++-- executables/nr-uesoftmodem.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index c3c871f172..5b6d21d177 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -76,7 +76,7 @@ #define CONFIG_HLP_ULMCS_PHYTEST "Set the uplink MCS for PHYTEST mode\n" #define CONFIG_HLP_DLBW_PHYTEST "Set the number of PRBs used for DLSCH in PHYTEST mode\n" #define CONFIG_HLP_ULBW_PHYTEST "Set the number of PRBs used for ULSCH in PHYTEST mode\n" -#define CONFIG_HLP_PRB "Set the number of PRBs for SA\n" +#define CONFIG_HLP_PRB_SA "Set the number of PRBs for SA\n" #define CONFIG_HLP_DLBM_PHYTEST "Bitmap for DLSCH slots (slot 0 starts at LSB)\n" #define CONFIG_HLP_ULBM_PHYTEST "Bitmap for ULSCH slots (slot 0 starts at LSB)\n" #define CONFIG_HLP_SSC "Set the start subcarrier \n" @@ -121,7 +121,7 @@ {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ {"G" , CONFIG_HLP_LOGV, 0, uptr:&glog_verbosity, defintval:0, TYPE_UINT16, 0}, \ {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ - {"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \ + {"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \ } #define CMDLINE_ONLINELOG_IDX 0 diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 52c0ee234c..6bbb75e559 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -57,7 +57,7 @@ {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ - {"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:106, TYPE_UINT, 0}, \ + {"r" , CONFIG_HLP_PRB_SA, 0, iptr:&(fp->N_RB_DL), defintval:106, TYPE_UINT, 0}, \ {"s" , CONFIG_HLP_SSC, 0, u16ptr:&(fp->ssb_start_subcarrier), defintval:516, TYPE_UINT16,0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ From 8fbc5a7146aead2b9c66a57dbb63cdce1fa81f3b Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 13 Aug 2021 16:19:36 +0200 Subject: [PATCH 144/185] fix sib1 detection in sa after merge --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index c110edf82e..38328ddb2e 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -1034,6 +1034,8 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_T(PHY,"Sequential dlsch decoding , ret = %d\n", ret); } + if(retmax_ldpc_iterations+1) + dec = true; switch (pdsch) { case RA_PDSCH: From 6d4437e607c7f54d73723e0e4dd2c63be6f36ed7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 13 Aug 2021 17:37:35 +0200 Subject: [PATCH 145/185] fix unnecessary error message in handle_nr_ul_harq during RA --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 10 +++++++++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 ++- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index d247aaa567..866a318fce 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -511,13 +511,21 @@ void abort_nr_ul_harq(module_id_t mod_id, int UE_id, int8_t harq_pid) sched_ctrl->sched_ul_bytes = 0; } -void handle_nr_ul_harq(module_id_t mod_id, +void handle_nr_ul_harq(const int CC_idP, + module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_crc_t *crc_pdu) { + gNB_MAC_INST *gNB_mac = RC.nrmac[mod_id]; int UE_id = find_nr_UE_id(mod_id, crc_pdu->rnti); if (UE_id < 0) { + for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { + NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; + if (ra->state >= WAIT_Msg3 && + ra->rnti == crc_pdu->rnti) + return; + } LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUSCH\n", __func__, crc_pdu->rnti); return; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 3af813e010..46eed89b39 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -411,7 +411,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, const uint8_t ul_cqi, const uint16_t rssi); -void handle_nr_ul_harq(module_id_t mod_id, +void handle_nr_ul_harq(const int CC_idP, + module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_crc_t *crc_pdu); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index fa76fd00bc..416cc16455 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -144,7 +144,7 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) rx->timing_advance, rx->ul_cqi, rx->rssi); - handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); + handle_nr_ul_harq(UL_info->CC_id, UL_info->module_id, UL_info->frame, UL_info->slot, crc); break; } // for (j=0;jcrc_ind.number_crcs;j++) } // for (i=0;irx_ind.number_of_pdus;i++) From 255a5acbfa0f2e38f21750f3d65bed9d2bed5683 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sat, 14 Aug 2021 09:05:49 +0530 Subject: [PATCH 146/185] Made FD interpolation by default PRB based averaging can activated from command line options --- executables/nr-gnb.c | 2 +- executables/nr-uesoftmodem.c | 4 ++-- executables/nr-uesoftmodem.h | 2 +- executables/softmodem-common.h | 8 ++++---- openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 4 ++-- openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 4 ++-- openair1/PHY/defs_gNB.h | 2 +- openair1/PHY/defs_nr_UE.h | 6 +++--- openair1/SIMULATION/NR_PHY/dlsim.c | 6 +++--- openair1/SIMULATION/NR_PHY/ulsim.c | 6 +++--- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 64146f19c1..ae7909769d 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -536,7 +536,7 @@ void init_gNB(int single_thread_flag,int wait_for_sync) { gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list;*/ gNB->prach_energy_counter = 0; - gNB->fd_interpolation = get_softmodem_params()->fd_interpolation; + gNB->prb_interpolation = get_softmodem_params()->prb_interpolation; } diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 082ab21fdc..1c3def6a91 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -321,8 +321,8 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->rf_map.chain = CC_id + chain_offset; - LOG_I(PHY,"Set UE mode %d, UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, fd_lin_interpolation %d", - UE->mode, UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->fd_lin_interpolation); + LOG_I(PHY,"Set UE mode %d, UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, do_prb_interpolation %d\n", + UE->mode, UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->prb_interpolation); // Set FP variables diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 311630abab..3eba5731b0 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -62,7 +62,7 @@ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ - {"do-fd-interpolation", CONFIG_HLP_FDINTER, PARAMFLAG_BOOL, iptr:&(UE->fd_lin_interpolation), defintval:0, TYPE_INT, 0}, \ + {"do-prb-interpolation", CONFIG_HLP_PRBINTER, PARAMFLAG_BOOL, iptr:&(UE->prb_interpolation), defintval:0, TYPE_INT, 0}, \ } diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 6e49e1554f..76904f2368 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -72,7 +72,7 @@ extern "C" #define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" #define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" #define CONFIG_HLP_256QAM "Use the 256 QAM mcs table for PDSCH\n" -#define CONFIG_HLP_FDINTER "Do frequency domain linear interpolation for channel estimates. By default, average of estimates over 1 PRB is used\n" +#define CONFIG_HLP_PRBINTER "Do PRB based averaging of channel estimates. Frequency domain linear interpolation by default\n" #define CONFIG_HLP_NONSTOP "Go back to frame sync mode after 100 consecutive PBCH failures\n" //#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation" @@ -120,7 +120,7 @@ extern "C" #define SEND_DMRSSYNC softmodem_params.send_dmrs_sync #define USIM_TEST softmodem_params.usim_test #define USE_256QAM_TABLE softmodem_params.use_256qam_table -#define FD_INTERPOLATION softmodem_params.fd_interpolation +#define PRB_INTERPOLATION softmodem_params.prb_interpolation #define NFAPI softmodem_params.nfapi #define NON_STOP softmodem_params.non_stop @@ -155,7 +155,7 @@ extern int usrp_tx_thread; {"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \ {"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \ - {"do-fd-interpolation", CONFIG_HLP_FDINTER, PARAMFLAG_BOOL, iptr:&FD_INTERPOLATION, defintval:0, TYPE_INT, 0}, \ + {"do-prb-interpolation", CONFIG_HLP_PRBINTER, PARAMFLAG_BOOL, iptr:&PRB_INTERPOLATION, defintval:0, TYPE_INT, 0}, \ {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \ {"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \ {"non-stop", CONFIG_HLP_NONSTOP, PARAMFLAG_BOOL, iptr:&NON_STOP, defintval:0, TYPE_INT, 0}, \ @@ -249,7 +249,7 @@ typedef struct { int hw_timing_advance; uint32_t send_dmrs_sync; int use_256qam_table; - int fd_interpolation; + int prb_interpolation; uint8_t nfapi; int non_stop; } softmodem_params_t; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 573060426e..39b80da068 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -187,7 +187,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #endif //if ((gNB->frame_parms.N_RB_UL&1)==0) { - if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && gNB->fd_interpolation == 1){ + if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1 && gNB->prb_interpolation == 0){ LOG_D(PHY,"PUSCH estimation DMRS type 1, Freq-domain interpolation"); // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -432,7 +432,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } #endif } - else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && gNB->fd_interpolation == 1) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| + else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && gNB->prb_interpolation == 0) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| LOG_D(PHY,"PUSCH estimation DMRS type 2, Freq-domain interpolation"); // Treat first DMRS specially (left edge) 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 1d6a960716..8097b9b3ea 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -785,7 +785,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, printf("rxF addr %p p %d\n", rxF,p); printf("dl_ch addr %p nushift %d\n",dl_ch,nushift); #endif - if (config_type == NFAPI_NR_DMRS_TYPE1 && ue->fd_lin_interpolation == 1) { + if (config_type == NFAPI_NR_DMRS_TYPE1 && ue->prb_interpolation == 0) { // Treat first 2 pilots specially (left edge) ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); @@ -962,7 +962,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, 8); } } - } else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->fd_lin_interpolation == 1){ //pdsch_dmrs_type2 |dmrs_r,dmrs_l,0,0,0,0,dmrs_r,dmrs_l,0,0,0,0| + } else if (config_type == NFAPI_NR_DMRS_TYPE2 && ue->prb_interpolation == 0){ //pdsch_dmrs_type2 |dmrs_r,dmrs_l,0,0,0,0,dmrs_r,dmrs_l,0,0,0,0| // Treat first 4 pilots specially (left edge) ch_l[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index a722dbe723..778724218f 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -840,7 +840,7 @@ typedef struct PHY_VARS_gNB_s { int **dl_precoder_SgNB[3]; char log2_maxp; /// holds the maximum channel/precoder coefficient - int fd_interpolation; + int prb_interpolation; /// if ==0 enables phy only test mode int mac_enabled; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 4d62ca7aed..c4a771294a 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -861,9 +861,9 @@ typedef struct { uint32_t perfect_ce; - // flag to activate linear interpolation in frequency-domain channel estimation - // when off (default), this just averages channel on per-PRB basis - int fd_lin_interpolation; + // flag to activate PRB based averaging of channel estimates + // when off, defaults to frequency domain interpolation + int prb_interpolation; int16_t ch_est_alpha; int generate_ul_signal[NUMBER_OF_CONNECTED_gNB_MAX]; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f5b8d39278..7a3e5aeccb 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -477,7 +477,7 @@ int main(int argc, char **argv) break; case 'i': - fd_inter=1; + prb_inter=1; break; case 'n': @@ -638,7 +638,7 @@ int main(int argc, char **argv) printf("-g [A,B,C,D,E,F,G,R] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models or R for MIMO model (ignores delay spread and Ricean factor)\n"); printf("-y Number of TX antennas used in gNB\n"); printf("-z Number of RX antennas used in UE\n"); - printf("-i Activate freq domain interpolation for channel estimation. Average over 1 PRB by default.\n"); + printf("-i Activate PRB based averaging for channel estimation. Frequncy domain interpolation by default.\n"); //printf("-j Relative strength of second intefering gNB (in dB) - cell_id mod 3 = 2\n"); printf("-R N_RB_DL\n"); printf("-O oversampling factor (1,2,4,8,16)\n"); @@ -905,7 +905,7 @@ int main(int argc, char **argv) UE->if_inst->phy_config_request = nr_ue_phy_config_request; UE->if_inst->dl_indication = nr_ue_dl_indication; UE->if_inst->ul_indication = dummy_nr_ue_ul_indication; - UE->fd_lin_interpolation = fd_inter; + UE->prb_interpolation = prb_inter; UE_mac->if_module = nr_ue_if_module_init(0); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 8c5ca677c5..c57b5f56e6 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -425,7 +425,7 @@ int main(int argc, char **argv) break; case 'i': - fd_inter=1; + prb_inter=1; break; case 'k': @@ -587,7 +587,7 @@ int main(int argc, char **argv) printf("-f Number of frames to simulate\n"); printf("-g [A,B,C,D,E,F,G] Use 3GPP SCM (A,B,C,D) or 36-101 (E-EPA,F-EVA,G-ETU) models (ignores delay spread and Ricean factor)\n"); printf("-h This message\n"); - printf("-i Activate freq domain interpolation for channel estimation. Average over 1 PRB by default.\n"); + printf("-i Activate PRB based averaging for channel estimation. Frequncy domain interpolation by default.\n"); //printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n"); printf("-s Starting SNR, runs from SNR0 to SNR0 + 10 dB if ending SNR isn't given\n"); printf("-m MCS value\n"); @@ -675,7 +675,7 @@ int main(int argc, char **argv) gNB->UL_INFO.crc_ind.crc_list = (nfapi_nr_crc_t *)malloc(NB_UE_INST*sizeof(nfapi_nr_crc_t)); gNB->UL_INFO.rx_ind.number_of_pdus = 0; gNB->UL_INFO.crc_ind.number_crcs = 0; - gNB->fd_interpolation = fd_inter; + gNB->prb_interpolation = prb_inter; frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH) From 5b378465241883e5c08d89d32445658d03972707 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sat, 14 Aug 2021 10:59:25 +0530 Subject: [PATCH 147/185] Fixed build error & warnings --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 36e185a19d..e407600d0f 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -387,7 +387,7 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH // do some integer rounding to improve TA accuracy if (sync_pos > 0) sync_pos_rounded = sync_pos + (bw_scaling / 2) - 1; - else if(sync_pos < 0) + else sync_pos_rounded = sync_pos - (bw_scaling / 2) - 1; timing_advance_update = sync_pos_rounded / bw_scaling; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 7a3e5aeccb..89197aaf3f 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -409,7 +409,7 @@ int main(int argc, char **argv) uint16_t rbSize = 106; uint8_t mcsIndex = 9; uint8_t dlsch_threads = 0; - int fd_inter = 0; + int prb_inter = 0; if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) { exit_fun("[NR_DLSIM] Error, configuration module init failed\n"); } diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index c57b5f56e6..80b704a19c 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -298,7 +298,7 @@ int main(int argc, char **argv) float effRate; //float eff_tp_check = 0.7; uint8_t snrRun; - int fd_inter = 0; + int prb_inter = 0; int enable_ptrs = 0; int modify_dmrs = 0; From 13980b5ebb871e5e6246ea67c083ef0fba9716d6 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 15 Aug 2021 16:23:25 +0200 Subject: [PATCH 148/185] msg3 retransmission at UE --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 4 +- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 6 +- .../NR_MAC_UE/nr_ue_dci_configuration.c | 3 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 79 +++++++++++++------ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 10 ++- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 + .../NR_MAC_gNB/gNB_scheduler_primitives.c | 54 ++++++++----- 7 files changed, 103 insertions(+), 55 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index cffdf5092d..b94d553c8b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -963,7 +963,8 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, currentPtrDCI); n_rnti = rel15->rnti; - LOG_D(PHY, "(%i.%i) dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d)\n", proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length); + LOG_D(PHY, "(%i.%i) dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d)\n", + proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length); if (crc == n_rnti) { LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %s,n_CCE %d,payloadSize %d,payload %llx)\n", proc->frame_rx, proc->nr_slot_rx,n_rnti,nr_dci_format_string[rel15->dci_format_options[k]],CCEind,dci_length,*(unsigned long long*)dci_estimation); @@ -990,6 +991,7 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, } } } + pdcch_vars->nb_search_space = 0; return(dci_ind->number_of_dcis); } diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 99edbf9a40..1b43f6a7f6 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -69,7 +69,8 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ for (i = 0; i < dl_config->number_pdus; ++i){ AssertFatal(dl_config->number_pdus < FAPI_NR_DL_CONFIG_LIST_NUM,"dl_config->number_pdus %d out of bounds\n",dl_config->number_pdus); AssertFatal(dl_config->dl_config_list[i].pdu_type<=FAPI_NR_DL_CONFIG_TYPES,"pdu_type %d > 2\n",dl_config->dl_config_list[i].pdu_type); - LOG_D(PHY, "In %s: received 1 DL %s PDU of %d total DL PDUs:\n", __FUNCTION__, dl_pdu_type[dl_config->dl_config_list[i].pdu_type - 1], dl_config->number_pdus); + LOG_D(PHY, "In %s: frame %d slot %d received 1 DL %s PDU of %d total DL PDUs:\n", + __FUNCTION__, scheduled_response->frame, slot, dl_pdu_type[dl_config->dl_config_list[i].pdu_type - 1], dl_config->number_pdus); if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_DCI) { @@ -145,7 +146,8 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->nEpreRatioOfPDSCHToPTRS = dlsch_config_pdu->nEpreRatioOfPDSCHToPTRS; dlsch0_harq->PTRSReOffset = dlsch_config_pdu->PTRSReOffset; dlsch0_harq->pduBitmap = dlsch_config_pdu->pduBitmap; - LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\tpdsch_to_harq_feedback_time_ind = %d\tslot_for_feedback_ack = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs, dlsch_config_pdu->pdsch_to_harq_feedback_time_ind, dlsch0_harq->harq_ack.slot_for_feedback_ack); + LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\tpdsch_to_harq_feedback_time_ind = %d\tslot_for_feedback_ack = %d\n", + dlsch0->g_pucch, dlsch0_harq->mcs, dlsch_config_pdu->pdsch_to_harq_feedback_time_ind, dlsch0_harq->harq_ack.slot_for_feedback_ack); } } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 8891d3354e..ae5a3c6695 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -183,7 +183,8 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); rel15->BWPStart = NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; - rel15->dci_length_options[0] = nr_dci_size(initialUplinkBWP, mac->cg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[0]], rel15->dci_format_options[0], NR_RNTI_TC, rel15->BWPSize, bwp_id); + for (int i = 0; i < rel15->num_dci_options; i++) + rel15->dci_length_options[i] = nr_dci_size(initialUplinkBWP, mac->cg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[i]], rel15->dci_format_options[i], NR_RNTI_TC, rel15->BWPSize, bwp_id); break; case NR_RNTI_SP_CSI: break; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index a72d7dc23d..12534d3563 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1465,6 +1465,11 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, pos++; dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; + //switch to DCI_0_0 + if (dci_pdu_rel15->format_indicator == 0) + return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, dci_pdu, dci_pdu_rel15); + + if (dci_pdu_rel15->format_indicator == 0) return 1; // discard dci, format indicator not corresponding to dci_format @@ -1603,40 +1608,62 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, break; case NR_RNTI_TC: - /* - // indicating a DL DCI format 1bit - dci_pdu->= (*dci_pdu>>(dci_size-pos)format_indicator&1)<<(dci_size-pos++); - // Freq domain assignment max 16 bit + //Identifier for DCI formats + pos++; + dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"Format indicator %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,dci_size-pos,*dci_pdu); +#endif + if (dci_pdu_rel15->format_indicator == 1) + return 1; // discard dci, format indicator not corresponding to dci_format fsize = (int)ceil( log2( (N_RB_UL*(N_RB_UL+1))>>1 ) ); - for (int i=0; i= ((*dci_pdu>>(dci_size-pos)frequency_domain_assignment>>(fsize-i-1))&1)<<(dci_size-pos++); + pos+=fsize; + dci_pdu_rel15->frequency_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu); +#endif // Time domain assignment 4bit - for (int i=0; i<4; i++) - dci_pdu->= (((uint64_t)*dci_pdu>>(dci_size-pos)time_domain_assignment>>(3-i))&1)<<(dci_size-pos++); + pos+=4; + dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu>>(dci_size-pos))&0xf; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"time-domain assignment %d (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu); +#endif // Frequency hopping flag  E1 bit - dci_pdu->= ((uint64_t)*dci_pdu>>(dci_size-pos)frequency_hopping_flag&1)<<(dci_size-pos++); + pos++; + dci_pdu_rel15->frequency_hopping_flag.val= (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"frequency_hopping %d (1 bit)=> %d (0x%lx)\n",dci_pdu_rel15->frequency_hopping_flag.val,dci_size-pos,*dci_pdu); +#endif // MCS 5 bit - for (int i=0; i<5; i++) - dci_pdu->= (((uint64_t)*dci_pdu>>(dci_size-pos)mcs>>(4-i))&1)<<(dci_size-pos++); + pos+=5; + dci_pdu_rel15->mcs= (*dci_pdu>>(dci_size-pos))&0x1f; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"mcs %d (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu); +#endif // New data indicator 1bit - dci_pdu->= ((uint64_t)*dci_pdu>>(dci_size-pos)ndi&1)<<(dci_size-pos++); + pos++; + dci_pdu_rel15->ndi= (*dci_pdu>>(dci_size-pos))&1; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu); +#endif // Redundancy version 2bit - for (int i=0; i<2; i++) - dci_pdu->= (((uint64_t)*dci_pdu>>(dci_size-pos)rv>>(1-i))&1)<<(dci_size-pos++); + pos+=2; + dci_pdu_rel15->rv= (*dci_pdu>>(dci_size-pos))&3; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu); +#endif // HARQ process number 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)*dci_pdu>>(dci_size-pos)harq_pid>>(3-i))&1)<<(dci_size-pos++); - + pos+=4; + dci_pdu_rel15->harq_pid = (*dci_pdu>>(dci_size-pos))&0xf; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu); +#endif // TPC command for scheduled PUSCH  E2 bits - for (int i=0; i<2; i++) - dci_pdu->= (((uint64_t)*dci_pdu>>(dci_size-pos)tpc>>(1-i))&1)<<(dci_size-pos++); - */ - // UL/SUL indicator  E1 bit - /* - commented for now (RK): need to get this information from BWP descriptor - if (cfg->pucch_config.pucch_GroupHopping.value) - dci_pdu->= ((uint64_t)dci_pdu_rel15->ul_sul_indicator&1)<<(dci_size-pos++); - */ + pos+=2; + dci_pdu_rel15->tpc = (*dci_pdu>>(dci_size-pos))&3; +#ifdef DEBUG_EXTRACT_DCI + LOG_I(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu); +#endif break; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 8916555f18..d2d4925e78 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -941,12 +941,15 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in } // this is for Msg2/Msg4 if (mac->ra.ra_state >= WAIT_RAR) { - rel15->num_dci_options = 1; + rel15->num_dci_options = mac->ra.ra_state == WAIT_RAR ? 1 : 2; rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + if (mac->ra.ra_state == WAIT_CONTENTION_RESOLUTION) + rel15->dci_format_options[1] = NR_UL_DCI_FORMAT_0_0; // msg3 retransmission config_dci_pdu(mac, rel15, dl_config, mac->ra.ra_state == WAIT_RAR ? NR_RNTI_RA : NR_RNTI_TC , -1); fill_dci_search_candidates(ss0, rel15); dl_config->number_pdus = 1; - LOG_D(NR_MAC,"mac->cg %p: Calling fill_scheduled_response rnti %x, type0_pdcch, num_pdus %d\n",mac->cg,rel15->rnti,dl_config->number_pdus); + LOG_D(NR_MAC,"mac->cg %p: Calling fill_scheduled_response rnti %x, type0_pdcch, num_pdus %d frame %d slot %d\n", + mac->cg,rel15->rnti,dl_config->number_pdus,rx_frame,rx_slot); fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) mac->if_module->scheduled_response(&scheduled_response); @@ -1014,7 +1017,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) { uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size; - LOG_D(NR_MAC,"harq_id %d, NDI %d NDI_DCI %d, TBS_bytes %d (ra_state %d\n", + LOG_D(NR_MAC,"harq_id %d, NDI %d NDI_DCI %d, TBS_bytes %d (ra_state %d)\n", ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id, mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id], ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator, @@ -1119,7 +1122,6 @@ int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, int delta = 0; NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; - // Get the numerology to calculate the Tx frame and slot int mu = ubwp ? ubwp->bwp_Common->genericParameters.subcarrierSpacing : diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 1500884251..ecdcc8bcc0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -859,6 +859,8 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t // reset state to wait msg3 ra->state = WAIT_Msg3; + ra->Msg3_frame = sched_frame; + ra->Msg3_slot = sched_slot; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index b595a89125..1bc9af193b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1387,41 +1387,53 @@ void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, break; case NFAPI_NR_RNTI_TC: - // indicating a DL DCI format 1bit - *dci_pdu |= (dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++); + // indicating a UL DCI format 1bit + pos=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos); // Freq domain assignment max 16 bit fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); - for (int i = 0; i < fsize; i++) - *dci_pdu |= ((dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + pos+=fsize; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos); // Time domain assignment 4bit - for (int i = 0; i < 4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + pos += 4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << 4) - 1)) << (dci_size - pos); // Frequency hopping flag – 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos++); + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos); // MCS 5 bit - for (int i = 0; i < 5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); + pos+=5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); // New data indicator 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++); + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos); // Redundancy version 2bit - for (int i = 0; i < 2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++); + pos+=2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); // HARQ process number 4bit - for (int i = 0; i < 4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++); - // TPC command for scheduled PUSCH – 2 bits - for (int i = 0; i < 2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++); + pos+=4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); // Padding bits for (int a = pos; a < 32; a++) *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++); // UL/SUL indicator – 1 bit - /* - commented for now (RK): need to get this information from BWP descriptor - if (cfg->pucch_config.pucch_GroupHopping.value) + /* commented for now (RK): need to get this from BWP descriptor + if (cfg->pucch_config.pucch_GroupHopping.value) *dci_pdu |= - ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); + ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); */ + LOG_D(NR_MAC,"N_RB = %i\n", N_RB); + LOG_D(NR_MAC,"dci_size = %i\n", dci_size); + LOG_D(NR_MAC,"fsize = %i\n", fsize); + LOG_D(NR_MAC,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + LOG_D(NR_MAC,"dci_pdu_rel15->frequency_hopping_flag.val = %i\n", dci_pdu_rel15->frequency_hopping_flag.val); + LOG_D(NR_MAC,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); + LOG_D(NR_MAC,"dci_pdu_rel15->ndi = %i\n", dci_pdu_rel15->ndi); + LOG_D(NR_MAC,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + LOG_D(NR_MAC,"dci_pdu_rel15->harq_pid = %i\n", dci_pdu_rel15->harq_pid); + LOG_D(NR_MAC,"dci_pdu_rel15->tpc = %i\n", dci_pdu_rel15->tpc); + LOG_D(NR_MAC,"dci_pdu_rel15->padding = %i\n", dci_pdu_rel15->padding); + break; } break; From d2b131af1dc60e4349197f5d6c9b936503bbdccf Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 15 Aug 2021 18:16:15 +0200 Subject: [PATCH 149/185] msg3 retransmission rounds at gnb --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 7 +++++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 10 +++++++++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 + 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index ecdcc8bcc0..919bbd07db 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -773,6 +773,7 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); fill_msg3_pusch_pdu(pusch_pdu, scc, + ra->msg3_round, startSymbolAndLength, ra->rnti, scs, bwpSize, bwpStart, @@ -956,6 +957,7 @@ void nr_get_Msg3alloc(module_id_t module_id, void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, NR_ServingCellConfigCommon_t *scc, + int round, int startSymbolAndLength, rnti_t rnti, int scs, int bwp_size, int bwp_start, @@ -1006,9 +1008,9 @@ void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, pusch_pdu->start_symbol_index = start_symbol_index; pusch_pdu->nr_of_symbols = nr_of_symbols; //Optional Data only included if indicated in pduBitmap - pusch_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 + pusch_pdu->pusch_data.rv_index = nr_rv_round_map[round]; pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 1; // new data + pusch_pdu->pusch_data.new_data_indicator = 1; pusch_pdu->pusch_data.num_cb = 0; pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, pusch_pdu->target_code_rate, @@ -1097,6 +1099,7 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t bwp_start = ibwp_start; fill_msg3_pusch_pdu(pusch_pdu,scc, + ra->msg3_round, startSymbolAndLength, ra->rnti, scs, ibwp_size, bwp_start, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 866a318fce..08823c23ca 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -795,7 +795,15 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, if( (frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot)) continue; - LOG_W(NR_MAC, "Random Access %i failed at state %i (CRC did not pass)\n", i, ra->state); + if (ra->msg3_round >= MAX_HARQ_ROUNDS - 1) { + LOG_W(NR_MAC, "Random Access %i failed at state %i (Reached msg3 max harq rounds)\n", i, ra->state); + nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); + return; + } + + LOG_W(NR_MAC, "Random Access %i Msg3 CRC did not pass)\n", i); + ra->msg3_round++; ra->state = Msg3_retransmission; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 46eed89b39..89bf273ca3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -138,6 +138,7 @@ void nr_fill_rar(uint8_t Mod_idP, void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, NR_ServingCellConfigCommon_t *scc, + int round, int startSymbolAndLength, rnti_t rnti, int scs, int bwp_size, int bwp_start, From f2fc22df81d1d32d58764f1de0c46fdbc89c73cf Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 16 Aug 2021 10:18:04 +0200 Subject: [PATCH 150/185] fix for dci_pdu format --- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 8 ++++---- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index c0020cc689..991eff76de 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -931,11 +931,11 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, if (pdsch == RA_PDSCH) { if (ue->prach_resources[gNB_id]!=NULL) - dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI; + dlsch0->rnti = ue->prach_resources[gNB_id]->ra_RNTI; else { - LOG_E(PHY,"[UE %d] Frame %d, nr_slot_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_slot_rx); - //mac_xface->macphy_exit("prach_resources is NULL"); - return; + LOG_E(PHY,"[UE %d] Frame %d, nr_slot_rx %d: FATAL, prach_resources is NULL\n", ue->Mod_id, frame_rx, nr_slot_rx); + //mac_xface->macphy_exit("prach_resources is NULL"); + return; } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 12534d3563..ab4529b87a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -1267,9 +1267,10 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; //switch to DCI_0_0 - if (dci_pdu_rel15->format_indicator == 0) + if (dci_pdu_rel15->format_indicator == 0) { + dci_pdu_rel15_t *dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, dci_pdu, dci_pdu_rel15); - + } #ifdef DEBUG_EXTRACT_DCI LOG_D(MAC,"Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,N_RB,dci_size-pos,*dci_pdu); #endif @@ -1466,9 +1467,10 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, dci_pdu_rel15->format_indicator = (*dci_pdu>>(dci_size-pos))&1; //switch to DCI_0_0 - if (dci_pdu_rel15->format_indicator == 0) + if (dci_pdu_rel15->format_indicator == 0) { + dci_pdu_rel15_t *dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, dci_pdu, dci_pdu_rel15); - + } if (dci_pdu_rel15->format_indicator == 0) return 1; // discard dci, format indicator not corresponding to dci_format From 02d86a889cdf45cf3d3e9a85044740b099c99f60 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 16 Aug 2021 11:53:58 +0200 Subject: [PATCH 151/185] additional fix for dci_pdu format --- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 2 -- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 9 ++++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 1b43f6a7f6..65f67e4760 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -264,9 +264,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ break; } } - memset(ul_config, 0, sizeof(fapi_nr_ul_config_request_t)); - } } return 0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index ab4529b87a..f2e0ba3ef7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -442,7 +442,10 @@ int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_in dci->rnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits); int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15); if ((ret&1) == 1) return -1; - else if (ret == 2) dci->dci_format = NR_UL_DCI_FORMAT_0_0; + else if (ret == 2) { + dci->dci_format = NR_UL_DCI_FORMAT_0_0; + def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format]; + } return (nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci->rnti, dci->dci_format)); } @@ -1268,7 +1271,7 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, //switch to DCI_0_0 if (dci_pdu_rel15->format_indicator == 0) { - dci_pdu_rel15_t *dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, dci_pdu, dci_pdu_rel15); } #ifdef DEBUG_EXTRACT_DCI @@ -1468,7 +1471,7 @@ uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, //switch to DCI_0_0 if (dci_pdu_rel15->format_indicator == 0) { - dci_pdu_rel15_t *dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, dci_pdu, dci_pdu_rel15); } From 275b82eab20756e70ecc52f2a6f39eaa4111a13a Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 16 Aug 2021 17:17:11 +0200 Subject: [PATCH 152/185] fix for contention resolution timer at NR UE --- .../NR_PHY/nr_dummy_functions_prach.c | 2 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 4 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 45 ++++++++++--------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c index a930c96a75..42296fb1b7 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c @@ -315,7 +315,7 @@ void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint mac->RA_attempt_number++; } -void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){ +void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id){ AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Starting contention resolution timer\n", mod_id, frameP); NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index f5953e7845..608b2d7b5b 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -292,8 +292,8 @@ typedef struct { /// Random-access Contention Resolution Timer active flag uint8_t RA_contention_resolution_timer_active; - /// Random-access Contention Resolution Timer count value - uint8_t RA_contention_resolution_cnt; + int RA_contention_resolution_target_frame; + int RA_contention_resolution_target_slot; /// Transmitted UE Contention Resolution Identifier uint8_t cont_res_id[6]; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index dac62cf9a6..3170d24ec7 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -360,7 +360,7 @@ void nr_get_prach_resources(module_id_t mod_id, void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id); -void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id); +void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); void nr_ue_msg2_scheduler(module_id_t mod_id, uint16_t rach_frame, uint16_t rach_slot, uint16_t *msg2_frame, uint16_t *msg2_slot); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 5d9126ad69..138b75ac74 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -457,18 +457,27 @@ void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint ra->RA_attempt_number++; } -void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){ +void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id){ NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = (mac->scc) ? + RA_config_t *ra = &mac->ra; + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = (mac->scc) ? mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup: mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; - RA_config_t *ra = &mac->ra; + long mu = (mac->scc) ? + mac->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing : + mac->scc_SIB->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + int subframes_per_slot = nr_slots_per_frame[mu]/10; - LOG_D(MAC,"In %s: [UE %d] Frame %d, CB-RA: starting contention resolution timer\n", __FUNCTION__, mod_id, frameP); + // start contention resolution timer (cnt in slots) + int RA_contention_resolution_timer_subframes = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) * 8; + + ra->RA_contention_resolution_target_frame = frameP + (RA_contention_resolution_timer_subframes/10); + ra->RA_contention_resolution_target_slot = (slotP + (RA_contention_resolution_timer_subframes * subframes_per_slot)) % nr_slots_per_frame[mu]; + + LOG_D(MAC,"In %s: [UE %d] CB-RA: starting contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n", + __FUNCTION__, mod_id, frameP, slotP, ra->RA_contention_resolution_target_frame, ra->RA_contention_resolution_target_slot); - // start contention resolution timer - ra->RA_contention_resolution_cnt = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) * 8; ra->RA_contention_resolution_timer_active = 1; ra->ra_state = WAIT_CONTENTION_RESOLUTION; @@ -736,20 +745,15 @@ void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame RA_config_t *ra = &mac->ra; if (ra->RA_contention_resolution_timer_active == 1) { - - ra->RA_contention_resolution_cnt--; - - LOG_D(MAC, "In %s: [%d.%d] RA contention resolution timer %d\n", __FUNCTION__, frame, slot, ra->RA_contention_resolution_cnt); - - if (ra->RA_contention_resolution_cnt == 0) { - ra->t_crnti = 0; - ra->RA_active = 0; - ra->RA_contention_resolution_timer_active = 0; - // Signal PHY to quit RA procedure - LOG_E(MAC, "[UE %d] CB-RA: Contention resolution timer has expired, RA procedure has failed...\n", module_id); - nr_ra_failed(module_id, cc_id, prach_resources, frame, slot); - } - + if (frame >= ra->RA_contention_resolution_target_frame && + slot >= ra->RA_contention_resolution_target_frame) { + ra->t_crnti = 0; + ra->RA_active = 0; + ra->RA_contention_resolution_timer_active = 0; + // Signal PHY to quit RA procedure + LOG_E(MAC, "[UE %d] CB-RA: Contention resolution timer has expired, RA procedure has failed...\n", module_id); + nr_ra_failed(module_id, cc_id, prach_resources, frame, slot); + } } } @@ -773,7 +777,6 @@ void nr_ra_succeeded(module_id_t mod_id, frame_t frame, int slot){ LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CB-RA: Contention Resolution is successful.\n", mod_id, frame, slot); - ra->RA_contention_resolution_cnt = -1; ra->RA_contention_resolution_timer_active = 0; mac->crnti = ra->t_crnti; ra->t_crnti = 0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 86ccd8b167..108845be79 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1091,7 +1091,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in if (ra->ra_state == WAIT_RAR && !ra->cfra){ LOG_I(NR_MAC,"[RAPROC] RA-Msg3 transmitted\n"); - nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, ul_info->frame_tx, ul_info->gNB_index); + nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->gNB_index); } } From 4fc24374d52699bf793c22f87797df082e170056 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 16 Aug 2021 17:42:07 +0200 Subject: [PATCH 153/185] fixes for contention resolution timer etc --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 6 +++--- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 138b75ac74..d26ec672b3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -470,12 +470,12 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot int subframes_per_slot = nr_slots_per_frame[mu]/10; // start contention resolution timer (cnt in slots) - int RA_contention_resolution_timer_subframes = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) * 8; + int RA_contention_resolution_timer_subframes = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1)<<3; ra->RA_contention_resolution_target_frame = frameP + (RA_contention_resolution_timer_subframes/10); ra->RA_contention_resolution_target_slot = (slotP + (RA_contention_resolution_timer_subframes * subframes_per_slot)) % nr_slots_per_frame[mu]; - LOG_D(MAC,"In %s: [UE %d] CB-RA: starting contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n", + LOG_I(MAC,"In %s: [UE %d] CB-RA: contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n", __FUNCTION__, mod_id, frameP, slotP, ra->RA_contention_resolution_target_frame, ra->RA_contention_resolution_target_slot); ra->RA_contention_resolution_timer_active = 1; @@ -746,7 +746,7 @@ void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame if (ra->RA_contention_resolution_timer_active == 1) { if (frame >= ra->RA_contention_resolution_target_frame && - slot >= ra->RA_contention_resolution_target_frame) { + slot >= ra->RA_contention_resolution_target_slot) { ra->t_crnti = 0; ra->RA_active = 0; ra->RA_contention_resolution_timer_active = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 7d485616c9..f73d66e4fe 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -793,7 +793,10 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]) bwp = ra->CellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]; - coreset = get_coreset(scc, bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); + if (*ss->controlResourceSetId == 0) + coreset = nr_mac->sched_ctrlCommon->coreset; // this is coreset 0 + else + coreset = get_coreset(scc, bwp, ss, NR_SearchSpace__searchSpaceType_PR_common); AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg3 retransmission\n"); nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->UL_dci_req[CC_id]; From 009f7fd94fbc78e01347d3b21796f33cc5b7d80b Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 16 Aug 2021 18:07:51 +0200 Subject: [PATCH 154/185] restart content resolution timer at each msg3 retransmission --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index d26ec672b3..0e5345ba89 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -475,7 +475,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot ra->RA_contention_resolution_target_frame = frameP + (RA_contention_resolution_timer_subframes/10); ra->RA_contention_resolution_target_slot = (slotP + (RA_contention_resolution_timer_subframes * subframes_per_slot)) % nr_slots_per_frame[mu]; - LOG_I(MAC,"In %s: [UE %d] CB-RA: contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n", + LOG_D(MAC,"In %s: [UE %d] CB-RA: contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n", __FUNCTION__, mod_id, frameP, slotP, ra->RA_contention_resolution_target_frame, ra->RA_contention_resolution_target_slot); ra->RA_contention_resolution_timer_active = 1; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 108845be79..1663c463e4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1089,11 +1089,15 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in tx_req.tx_request_body[0].pdu_index = j; tx_req.tx_request_body[0].pdu = ulsch_input_buffer; + if (ra->ra_state == WAIT_CONTENTION_RESOLUTION && !ra->cfra){ + LOG_I(NR_MAC,"[RAPROC] RA-Msg3 retransmitted\n"); + // 38.321 restart the ra-ContentionResolutionTimer at each HARQ retransmission in the first symbol after the end of the Msg3 transmission + nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->gNB_index); + } if (ra->ra_state == WAIT_RAR && !ra->cfra){ LOG_I(NR_MAC,"[RAPROC] RA-Msg3 transmitted\n"); nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, ul_info->frame_tx, ul_info->slot_tx, ul_info->gNB_index); } - } } From cdbdba56315ed796d38ac81095cbd95f1d3b5d05 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 17 Aug 2021 16:10:40 +0530 Subject: [PATCH 155/185] fixed merge --- .../CONF/gnb.band78.tm1.217PRB.usrpn300.conf | 18 ++++++------------ .../CONF/gnb.band78.tm1.217PRB.usrpx300.conf | 18 ++++++------------ .../CONF/gnb.band78.tm1.273PRB.usrpn300.conf | 18 ++++++------------ 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf index fbc028667a..9deee3d900 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf @@ -230,18 +230,12 @@ MACRLCs = ( ); L1s = ( - { -<<<<<<< HEAD - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 8; - ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 -======= - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 8; ->>>>>>> origin/develop - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf index 8be71b0056..24c2d845bd 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf @@ -214,18 +214,12 @@ MACRLCs = ( ); L1s = ( - { -<<<<<<< HEAD - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 8; - ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 -======= - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 8; ->>>>>>> origin/develop - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf index 53b4035f99..432eb26e0b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf @@ -214,18 +214,12 @@ MACRLCs = ( ); L1s = ( - { -<<<<<<< HEAD - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 8; - ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 -======= - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 8; ->>>>>>> origin/develop - } + { + num_cc = 1; + tr_n_preference = "local_mac"; + pusch_proc_threads = 8; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } ); RUs = ( From 7f5009d7cc24b9d016d465c517c6b9180797eb2b Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 17 Aug 2021 17:57:09 +0530 Subject: [PATCH 156/185] fixed SA issues --- openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c | 2 +- openair2/GNB_APP/L1_nr_paramdef.h | 1 - .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf | 2 +- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf | 2 +- .../GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index 4cebeab712..3908febae9 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -106,7 +106,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, { first_time = 0; ue->time_sync_cell = 1; - if (get_softmodem_params()->do_ra) { + if (get_softmodem_params()->do_ra || get_softmodem_params()->sa) { LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); //mac_resynch(); //dl_phy_sync_success(ue->Mod_id,frame,0,1);//ue->common_vars.eNb_id); diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h index 832e1a690c..0306713845 100644 --- a/openair2/GNB_APP/L1_nr_paramdef.h +++ b/openair2/GNB_APP/L1_nr_paramdef.h @@ -67,7 +67,6 @@ {CONFIG_STRING_L1_REMOTE_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:3, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_OFDM_OFFSET_DIVISOR, NULL, 0, uptr:NULL, defuintval:8, TYPE_UINT, 0}, \ -{CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:1, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_PUCCH0_DTX_THRESHOLD, NULL, 0, uptr:NULL, defintval:100, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_PRACH_DTX_THRESHOLD, NULL, 0, uptr:NULL, defintval:150, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_PUSCH_DTX_THRESHOLD, NULL, 0, uptr:NULL, defintval:50, TYPE_UINT, 0} \ diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf index 9deee3d900..7d8b80f83c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf @@ -235,7 +235,7 @@ L1s = ( tr_n_preference = "local_mac"; pusch_proc_threads = 8; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 - } + } ); RUs = ( diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf index 24c2d845bd..a1a4972470 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf @@ -219,7 +219,7 @@ L1s = ( tr_n_preference = "local_mac"; pusch_proc_threads = 8; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 - } + } ); RUs = ( diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf index 432eb26e0b..2b646fcacd 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf @@ -219,7 +219,7 @@ L1s = ( tr_n_preference = "local_mac"; pusch_proc_threads = 8; ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 - } + } ); RUs = ( From 38d1782f9b44bf388fef44756e3f0a14b6f787e6 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 19 Aug 2021 13:40:12 +0530 Subject: [PATCH 157/185] minor fixes (review comments) --- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 2 - openair1/PHY/defs_nr_UE.h | 1 - .../gnb.band22.tm1.106PRB.adrv9371zc706.conf | 291 ------------------ 3 files changed, 294 deletions(-) delete mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 8d0230de36..eae4a2eaa7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -445,8 +445,6 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //LOG_I(PHY, "avgs Power per SC is %d\n", avgs); median[(aatx*frame_parms->nb_antennas_rx)+aarx] = avg[(aatx*frame_parms->nb_antennas_rx)+aarx]; } - pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; - //LOG_I(PHY, "avgs Power per SC is %d lg2_maxh %d\n", avgs, pdsch_vars[gNB_id]->log2_maxh); if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { nr_dlsch_channel_level_median(pdsch_vars[gNB_id]->dl_ch_estimates_ext, diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index a352bbc75c..019d5e6259 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -868,7 +868,6 @@ typedef struct { // flag to activate PRB based averaging of channel estimates // when off, defaults to frequency domain interpolation int prb_interpolation; - int16_t ch_est_alpha; int generate_ul_signal[NUMBER_OF_CONNECTED_gNB_MAX]; UE_NR_SCAN_INFO_t scan_info[NB_BANDS_MAX]; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf deleted file mode 100644 index 10241eb9b5..0000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band22.tm1.106PRB.adrv9371zc706.conf +++ /dev/null @@ -1,291 +0,0 @@ -Active_gNBs = ( "gNB-Eurecom-5GNRBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -gNBs = -( - { - ////////// Identification parameters: - gNB_ID = 0xe00; - - cell_type = "CELL_MACRO_GNB"; - - gNB_name = "gNB-Eurecom-5GNRBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - - plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); - - tr_s_preference = "local_mac" - - ////////// Physical parameters: - - component_carriers = ( - { - node_function = "3GPP_gNODEB"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "TDD"; - DL_prefix_type = "NORMAL"; - UL_prefix_type = "NORMAL"; - eutra_band = 78; - downlink_frequency = 3510000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 106; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - MIB_subCarrierSpacingCommon = 30; - MIB_ssb_SubcarrierOffset = 0; - MIB_dmrs_TypeA_Position = 2; - pdcch_ConfigSIB1 = 0; - SIB1_frequencyOffsetSSB = "khz5"; - SIB1_ssb_PeriodicityServingCell = 5; - SIB1_ss_PBCH_BlockPower = -60; - absoluteFrequencySSB = 0; - DL_FreqBandIndicatorNR = 15; - DL_absoluteFrequencyPointA = 15; - DL_offsetToCarrier = 15; - DL_SCS_SubcarrierSpacing = "kHz30"; - DL_SCS_SpecificCarrier_k0 = 0; - DL_carrierBandwidth = 15; - DL_locationAndBandwidth = 15; - DL_BWP_SubcarrierSpacing = "kHz30"; - DL_BWP_prefix_type = "NORMAL"; - UL_FreqBandIndicatorNR = 15; - UL_absoluteFrequencyPointA = 13; - UL_additionalSpectrumEmission = 3; - UL_p_Max = -1; - UL_frequencyShift7p5khz = "TRUE"; - UL_offsetToCarrier = 10; - UL_SCS_SubcarrierSpacing = "kHz30"; - UL_SCS_SpecificCarrier_k0 = 0; - UL_carrierBandwidth = 15; - UL_locationAndBandwidth = 15; - UL_BWP_SubcarrierSpacing = "kHz30"; - UL_BWP_prefix_type = "NORMAL"; - UL_timeAlignmentTimerCommon = "infinity"; - ServingCellConfigCommon_n_TimingAdvanceOffset = "n0" - ServingCellConfigCommon_ssb_PositionsInBurst_PR = 0x01; - ServingCellConfigCommon_ssb_periodicityServingCell = 10; - ServingCellConfigCommon_dmrs_TypeA_Position = 2; - NIA_SubcarrierSpacing = "kHz15"; - ServingCellConfigCommon_ss_PBCH_BlockPower = -60; - referenceSubcarrierSpacing = "kHz15"; - dl_UL_TransmissionPeriodicity = "ms0p5"; - nrofDownlinkSlots = 10; - nrofDownlinkSymbols = 10; - nrofUplinkSlots = 10; - nrofUplinkSymbols = 10; - rach_totalNumberOfRA_Preambles = 63; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice = "oneEighth"; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf = 16; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one = 24; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two = 32; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four = 8; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight = 4; - rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen = 2; - rach_groupBconfigured = "ENABLE"; - rach_ra_Msg3SizeGroupA = 56; - rach_messagePowerOffsetGroupB = "dB0"; - rach_numberOfRA_PreamblesGroupA = 32; - rach_ra_ContentionResolutionTimer = 8; - rsrp_ThresholdSSB = 64; - rsrp_ThresholdSSB_SUL = 64; - prach_RootSequenceIndex_choice = "l839"; - prach_RootSequenceIndex_l839 = 0; - prach_RootSequenceIndex_l139 = 0; - prach_msg1_SubcarrierSpacing = "kHz30"; - restrictedSetConfig = "unrestrictedSet"; - msg3_transformPrecoding = "ENABLE"; - prach_ConfigurationIndex = 10; - prach_msg1_FDM = "one"; - prach_msg1_FrequencyStart = 10; - zeroCorrelationZoneConfig = 10; - preambleReceivedTargetPower = -150; - preambleTransMax = 6; - powerRampingStep = "dB0"; - ra_ResponseWindow = 8; - groupHoppingEnabledTransformPrecoding = "ENABLE"; - msg3_DeltaPreamble = 0; - p0_NominalWithGrant = 0; - PUSCH_TimeDomainResourceAllocation_k2 = 0; - PUSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PUSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - pucch_ResourceCommon = 0; - pucch_GroupHopping = "neither"; - hoppingId = 0; - p0_nominal = -30; - PDSCH_TimeDomainResourceAllocation_k0 = 2; - PDSCH_TimeDomainResourceAllocation_mappingType = "typeA"; - PDSCH_TimeDomainResourceAllocation_startSymbolAndLength = 0; - rateMatchPatternId = 0; - RateMatchPattern_patternType = "bitmaps"; - symbolsInResourceBlock = "oneSlot"; - periodicityAndPattern = 2; - RateMatchPattern_controlResourceSet = 5; - RateMatchPattern_subcarrierSpacing = "kHz30"; - RateMatchPattern_mode = "dynamic"; - controlResourceSetZero = 0; - searchSpaceZero = 0; - searchSpaceSIB1 = 10; - searchSpaceOtherSystemInformation = 10; - pagingSearchSpace = 10; - ra_SearchSpace = 10; - PDCCH_common_controlResourceSetId = 5; - PDCCH_common_ControlResourceSet_duration = 2; - PDCCH_cce_REG_MappingType = "nonInterleaved"; - PDCCH_reg_BundleSize = 3; - PDCCH_interleaverSize = 3; - PDCCH_shiftIndex = 10; - PDCCH_precoderGranularity = "sameAsREG-bundle"; - PDCCH_TCI_StateId = 32; - tci_PresentInDCI = "ENABLE"; - PDCCH_DMRS_ScramblingID = 0; - SearchSpaceId = 10; - commonSearchSpaces_controlResourceSetId = 5; - SearchSpace_monitoringSlotPeriodicityAndOffset_choice = "sl1"; - SearchSpace_monitoringSlotPeriodicityAndOffset_value = 0; - SearchSpace_duration = 2; - SearchSpace_nrofCandidates_aggregationLevel1 = 0; - SearchSpace_nrofCandidates_aggregationLevel2 = 0; - SearchSpace_nrofCandidates_aggregationLevel4 = 0; - SearchSpace_nrofCandidates_aggregationLevel8 = 0; - SearchSpace_nrofCandidates_aggregationLevel16 = 0; - SearchSpace_searchSpaceType = "common"; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8 = 1; - Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16 = 1; - Common_dci_Format2_3_monitoringPeriodicity = 1; - Common_dci_Format2_3_nrofPDCCH_Candidates = 1; - ue_Specific__dci_Formats = "formats0-0-And-1-0"; - RateMatchPatternLTE_CRS_carrierFreqDL = 6; - RateMatchPatternLTE_CRS_carrierBandwidthDL = 6; - RateMatchPatternLTE_CRS_nrofCRS_Ports = 1; - RateMatchPatternLTE_CRS_v_Shift = 0; - RateMatchPatternLTE_CRS_radioframeAllocationPeriod = 1; - RateMatchPatternLTE_CRS_radioframeAllocationOffset = 0; - RateMatchPatternLTE_CRS_subframeAllocation_choice = "oneFrame"; - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.26"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - NETWORK_INTERFACES : - { - - GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; - GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - } -); - -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - } -); - -L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - pusch_proc_threads = 8; - ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 - } -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 114; - eNB_instances = [0]; - sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,mgmt_addr=192.168.100.8"; - - } -); - -NETWORK_CONTROLLER : -{ - FLEXRAN_ENABLED = "no"; - FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; - FLEXRAN_PORT = 2210; - FLEXRAN_CACHE = "/mnt/oai_agent_cache"; - FLEXRAN_AWAIT_RECONF = "no"; -}; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - From 1d09adc74cf97445c268b8916757ba2e5cdf058c Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 20 Aug 2021 18:06:53 +0200 Subject: [PATCH 158/185] fixes for msg4 retransmission --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 42 ++++++++++++------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 2 +- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 220b4a921e..5e245748dc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1210,11 +1210,15 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra long BWPSize = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); long BWPStart = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); + /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ + int current_harq_pid = sched_ctrl->retrans_dl_harq.head; // HARQ management - AssertFatal(sched_ctrl->available_dl_harq.head >= 0, - "UE context not initialized: no HARQ processes found\n"); - int current_harq_pid = sched_ctrl->available_dl_harq.head; - remove_front_nr_list(&sched_ctrl->available_dl_harq); + if (current_harq_pid < 0) { + AssertFatal(sched_ctrl->available_dl_harq.head >= 0, + "UE context not initialized: no HARQ processes found\n"); + current_harq_pid = sched_ctrl->available_dl_harq.head; + remove_front_nr_list(&sched_ctrl->available_dl_harq); + } NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; DevAssert(!harq->is_waiting); add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); @@ -1522,24 +1526,32 @@ void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_fram NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; NR_UE_harq_t *harq = &UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid]; + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; LOG_D(NR_MAC, "ue %d, rnti %d, harq is waiting %d, round %d, frame %d %d, harq id %d\n", UE_id, ra->rnti, harq->is_waiting, harq->round, frame, slot, current_harq_pid); - if (harq->is_waiting == 0) - { - if (harq->round == 0) - { - LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", UE_id, ra->rnti); - nr_clear_ra_proc(module_id, CC_id, frame, ra); - UE_info->active[UE_id] = true; - UE_info->Msg4_ACKed[UE_id] = true; + if (harq->is_waiting == 0) { + if (harq->round == 0) { + if (stats->dlsch_errors == 0) { + LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", UE_id, ra->rnti); + nr_clear_ra_proc(module_id, CC_id, frame, ra); + UE_info->active[UE_id] = true; + UE_info->Msg4_ACKed[UE_id] = true; + } + else { + LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) RA Procedure failed at Msg4!\n", UE_id, ra->rnti); + nr_mac_remove_ra_rnti(module_id, ra->rnti); + nr_clear_ra_proc(module_id, CC_id, frame, ra); + mac_remove_nr_ue(module_id, ra->rnti); + } } - else - { + else { + LOG_I(NR_MAC, "(ue %i, rnti 0x%04x) Received Nack of RA-Msg4. Preparing retransmission!\n", UE_id, ra->rnti); + ra->Msg4_frame = (frame + 1) % 1024; + ra->Msg4_slot = 1; ra->state = Msg4; } } - } void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t *ra){ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index fbd8a4b5ca..36673d8d99 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -770,7 +770,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, nr_process_mac_pdu(gnb_mod_idP, UE_id, CC_idP, frameP, slotP, sduP, sdu_lenP); ra->state = Msg4; - ra->Msg4_frame = ( frameP +2 ) % 1024; + ra->Msg4_frame = (frameP + 2) % 1024; ra->Msg4_slot = 1; LOG_I(NR_MAC, "Scheduling RA-Msg4 for TC_RNTI %04x (state %d, frame %d, slot %d)\n", ra->rnti, ra->state, ra->Msg4_frame, ra->Msg4_slot); From cebe8b79972de0c6a1a1d4ed9a20ba7d54223397 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 20 Aug 2021 18:34:18 +0200 Subject: [PATCH 159/185] do not process rar in case of nack --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 76 +++++++++++--------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 1d18c8ef3e..3a106d7d6c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3560,6 +3560,12 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t module_id_t mod_id = dl_info->module_id; frame_t frame = dl_info->frame; int slot = dl_info->slot; + + if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack == 0) { + LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] CRC check failed on RAR (NAK)\n", mod_id, frame, slot); + return 0; + } + int cc_id = dl_info->cc_id; uint8_t gNB_id = dl_info->gNB_index; NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); @@ -3622,46 +3628,46 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t unsigned char csi_req; #endif - // TC-RNTI - ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); + // TC-RNTI + ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); - // TA command - ul_time_alignment->apply_ta = 1; - ul_time_alignment->ta_command = 31 + rar->TA2 + (rar->TA1 << 5); + // TA command + ul_time_alignment->apply_ta = 1; + ul_time_alignment->ta_command = 31 + rar->TA2 + (rar->TA1 << 5); #ifdef DEBUG_RAR - // CSI - csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); + // CSI + csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); #endif - // TPC - tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); - switch (tpc_command){ - case 0: - ra->Msg3_TPC = -6; - break; - case 1: - ra->Msg3_TPC = -4; - break; - case 2: - ra->Msg3_TPC = -2; - break; - case 3: - ra->Msg3_TPC = 0; - break; - case 4: - ra->Msg3_TPC = 2; - break; - case 5: - ra->Msg3_TPC = 4; - break; - case 6: - ra->Msg3_TPC = 6; - break; - case 7: - ra->Msg3_TPC = 8; - break; - } + // TPC + tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); + switch (tpc_command){ + case 0: + ra->Msg3_TPC = -6; + break; + case 1: + ra->Msg3_TPC = -4; + break; + case 2: + ra->Msg3_TPC = -2; + break; + case 3: + ra->Msg3_TPC = 0; + break; + case 4: + ra->Msg3_TPC = 2; + break; + case 5: + ra->Msg3_TPC = 4; + break; + case 6: + ra->Msg3_TPC = 6; + break; + case 7: + ra->Msg3_TPC = 8; + break; + } // MCS rar_grant.mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); // time alloc From 965945f9e7676de2ff2cfa58d124f88d16012298 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 22 Aug 2021 14:55:17 +0200 Subject: [PATCH 160/185] bugfix in dlsch scramblingid --- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index b1bf32b790..ce056b5aa5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -213,7 +213,7 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, nr_pdsch_codeword_scrambling_optim(harq->f, encoded_length, q, - rel15->dlDmrsScramblingId, + rel15->dataScramblingId, rel15->rnti, scrambled_output[q]); From 7ab05b666daa562e82490482cc47a9a5f54f264d Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 22 Aug 2021 18:06:45 +0200 Subject: [PATCH 161/185] reset dci at ue after processing --- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 2 -- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index ea12646395..a9ecc61ccb 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -225,9 +225,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ break; } } - memset(ul_config, 0, sizeof(fapi_nr_ul_config_request_t)); - } } return 0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 3a106d7d6c..0adc0a7cfc 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -513,7 +513,9 @@ int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_in int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15); if ((ret&1) == 1) return -1; else if (ret == 2) dci->dci_format = NR_UL_DCI_FORMAT_0_0; - return (nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci)); + int8_t ret_proc = nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci); + memset(def_dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t)); + return ret_proc; } int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, fapi_nr_dci_indication_pdu_t *dci_ind) { From d78861dbf01f7abf859343188c0d4eed64665924 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 23 Aug 2021 11:46:34 +0200 Subject: [PATCH 162/185] use the same buffer and size for msg4 retransmission --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 31 ++++++++++--------- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 ++ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 5e245748dc..89e0d62402 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1251,18 +1251,19 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra harq->feedback_slot = pucch->ul_slot; harq->feedback_frame = pucch->frame; - // Bytes to be transmitted uint8_t *buf = (uint8_t *) harq->tb; - uint16_t mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id); - LOG_D(NR_MAC,"Encoded contention resolution mac_pdu_length %d\n",mac_pdu_length); - uint16_t mac_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, CCCH, ra->rnti, 1, &buf[mac_pdu_length+2]); - ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->R = 0; - ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->F = 0; - ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->LCID = DL_SCH_LCID_CCCH; - ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->L = mac_sdu_length; - mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_SHORT); - - LOG_D(NR_MAC,"Encoded RRCSetup Piggyback (%d + %d bytes), mac_pdu_length %d\n", mac_sdu_length, (int)sizeof(NR_MAC_SUBHEADER_SHORT), mac_pdu_length); + // Bytes to be transmitted + if (harq->round == 0) { + uint16_t mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id); + LOG_D(NR_MAC,"Encoded contention resolution mac_pdu_length %d\n",mac_pdu_length); + uint16_t mac_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, CCCH, ra->rnti, 1, &buf[mac_pdu_length+2]); + ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->R = 0; + ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->F = 0; + ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->LCID = DL_SCH_LCID_CCCH; + ((NR_MAC_SUBHEADER_SHORT *) &buf[mac_pdu_length])->L = mac_sdu_length; + ra->mac_pdu_length = mac_pdu_length + mac_sdu_length + sizeof(NR_MAC_SUBHEADER_SHORT); + LOG_D(NR_MAC,"Encoded RRCSetup Piggyback (%d + %d bytes), mac_pdu_length %d\n", mac_sdu_length, (int)sizeof(NR_MAC_SUBHEADER_SHORT), ra->mac_pdu_length); + } // Calculate number of symbols int startSymbolIndex, nrOfSymbols; @@ -1323,7 +1324,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra harq->tb_size = nr_compute_tbs(nr_get_Qm_dl(mcsIndex, mcsTableIdx), nr_get_code_rate_dl(mcsIndex, mcsTableIdx), rbSize, nrOfSymbols, N_PRB_DMRS * N_DMRS_SLOT, 0, tb_scaling,1) >> 3; - } while (rbStart + rbSize < BWPSize && !vrb_map[rbStart + rbSize] && harq->tb_size < mac_pdu_length); + } while (rbStart + rbSize < BWPSize && !vrb_map[rbStart + rbSize] && harq->tb_size < ra->mac_pdu_length); for (int i = 0; (i < rbSize) && (rbStart <= (BWPSize - rbSize)); i++) { if (vrb_map[rbStart + i]) { @@ -1474,11 +1475,11 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra bwpid); // Add padding header and zero rest out if there is space left - if (mac_pdu_length < harq->tb_size) { - NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) &buf[mac_pdu_length]; + if (ra->mac_pdu_length < harq->tb_size) { + NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) &buf[ra->mac_pdu_length]; padding->R = 0; padding->LCID = DL_SCH_LCID_PADDING; - for(int k = mac_pdu_length+1; ktb_size; k++) { + for(int k = ra->mac_pdu_length+1; ktb_size; k++) { buf[k] = 0; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index bd88c39306..737c5e25b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -156,6 +156,8 @@ typedef struct { int msg4_TBsize; /// MCS used for Msg4 int msg4_mcs; + /// MAC PDU length for Msg4 + int mac_pdu_length; /// RA search space NR_SearchSpace_t *ra_ss; // Beam index From 3a07b6bf1bb4b0b5c0b4dc0754b3db6815e938e3 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 23 Aug 2021 11:55:20 +0200 Subject: [PATCH 163/185] rewriting downlink harq process function --- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 46 +++++------ .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 4 +- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 2 +- openair1/SCHED_NR_UE/harq_nr.c | 80 ++++++++++++------- openair1/SCHED_NR_UE/harq_nr.h | 2 +- 5 files changed, 78 insertions(+), 56 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index c98a685ed8..68006f853b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -155,7 +155,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint if (dlsch->harq_processes[i]) { memset(dlsch->harq_processes[i],0,sizeof(NR_DL_UE_HARQ_t)); init_downlink_harq_status(dlsch->harq_processes[i]); - dlsch->harq_processes[i]->first_tx=1; + dlsch->harq_processes[i]->first_rx=1; dlsch->harq_processes[i]->b = (uint8_t *)malloc16(dlsch_bytes); if (dlsch->harq_processes[i]->b) @@ -358,7 +358,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, } } - if (harq_process->round == 0) { + if (harq_process->first_rx == 1) { // This is a new packet, so compute quantities regarding segmentation if (A > NR_MAX_PDSCH_TBS) harq_process->B = A+24; @@ -448,7 +448,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, harq_process->w[r], harq_process->C, harq_process->rvidx, - (harq_process->round==0)?1:0, + (harq_process->first_rx==1)?1:0, E, harq_process->F, Kr-harq_process->F-2*(p_decParams->Z))==-1) { @@ -771,7 +771,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, } } - if (harq_process->round == 0) { + if (harq_process->first_rx == 1) { // This is a new packet, so compute quantities regarding segmentation if (A > NR_MAX_PDSCH_TBS) harq_process->B = A+24; @@ -909,7 +909,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, harq_process->w[r], harq_process->C, harq_process->rvidx, - (harq_process->round==0)?1:0, + (harq_process->first_rx==1)?1:0, E, harq_process->F, Kr-harq_process->F-2*(p_decParams->Z))==-1) { @@ -1229,25 +1229,23 @@ void nr_dlsch_decoding_process(void *arg) { } } - harq_process->round =0; + if (harq_process->first_rx == 1) { + // This is a new packet, so compute quantities regarding segmentation + if (A > NR_MAX_PDSCH_TBS) + harq_process->B = A+24; + else + harq_process->B = A+16; - // if (harq_process->round == 0) { - // This is a new packet, so compute quantities regarding segmentation - if (A > NR_MAX_PDSCH_TBS) - harq_process->B = A+24; - else - harq_process->B = A+16; - - nr_segmentation(NULL, - NULL, - harq_process->B, - &harq_process->C, - &harq_process->K, - &harq_process->Z, - &harq_process->F, - p_decParams->BG); - p_decParams->Z = harq_process->Z; - // } + nr_segmentation(NULL, + NULL, + harq_process->B, + &harq_process->C, + &harq_process->K, + &harq_process->Z, + &harq_process->F, + p_decParams->BG); + p_decParams->Z = harq_process->Z; + } LOG_D(PHY,"round %d Z %d K %d BG %d\n", harq_process->round, p_decParams->Z, harq_process->K, p_decParams->BG); p_decParams->numMaxIter = dlsch->max_ldpc_iterations; p_decParams->outMode= 0; @@ -1314,7 +1312,7 @@ void nr_dlsch_decoding_process(void *arg) { harq_process->w[r], harq_process->C, harq_process->rvidx, - (harq_process->round==0)?1:0, + (harq_process->first_rx==1)?1:0, E, harq_process->F, Kr-harq_process->F-2*(p_decParams->Z))==-1) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index e8a9606255..b4ee4f5b41 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -206,8 +206,8 @@ typedef struct { } NR_UE_ULSCH_t; typedef struct { - /// Indicator of first transmission - uint8_t first_tx; + /// Indicator of first reception + uint8_t first_rx; /// Last Ndi received for this process on DCI (used for C-RNTI only) uint8_t DCINdi; /// DLSCH status flag indicating diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index a9ecc61ccb..d834e4c53f 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -126,7 +126,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ } dlsch0_harq->Nl = Nl; dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; - downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); + downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch_config_pdu->rv, dlsch0->rnti_type); if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE may be due to false retransmission. Reset the // following flag to skip PDSCH procedures in that case. diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 3f528f02d4..660cfbb910 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -306,7 +306,7 @@ harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, int ndi, u void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) { dl_harq->status = SCH_IDLE; - dl_harq->first_tx = 1; + dl_harq->first_rx = 1; dl_harq->round = 0; dl_harq->ack = DL_ACKNACK_NO_SET; } @@ -328,39 +328,63 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) * *********************************************************************/ -void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, uint8_t rnti_type) { +void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, int rv, uint8_t rnti_type) { - if (rnti_type == _CS_RNTI_) { - LOG_E(PHY, "Fatal error in HARQ entity due to not supported CS_RNTI at line %d in function %s of file %s \n", __LINE__ , __func__, __FILE__); - return; - } - else if ((rnti_type != _C_RNTI_) && (rnti_type != _TC_RNTI_)) { - /* harq mechanism is not relevant for other rnti */ - return; - } - if (dl_harq->first_tx == 1) { + if (rnti_type == _SI_RNTI_ || + rnti_type == _P_RNTI_ || + rnti_type == _RA_RNTI_) { dl_harq->round = 0; dl_harq->status = ACTIVE; - dl_harq->DCINdi = ndi; - dl_harq->first_tx = 0; - - LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] first new reception \n", harq_pid); + dl_harq->first_rx = 1; } - else if (dl_harq->DCINdi != ndi) { - dl_harq->round = 0; - dl_harq->status = ACTIVE; - dl_harq->DCINdi = ndi; - - LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] new reception due to toogle of ndi \n", harq_pid); + else{ + switch(rv){ + case 0: + dl_harq->round = 0; + dl_harq->status = ACTIVE; + dl_harq->first_rx = 1; + if (dl_harq->DCINdi == ndi) + LOG_E(PHY,"Warning! rv %d indicates new transmission but new ndi %d is the same as old ndi %d\n",rv,ndi,dl_harq->DCINdi); + dl_harq->DCINdi = ndi; + break; + case 1: + dl_harq->round = 2; + if (dl_harq->DCINdi != ndi) { + LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); + dl_harq->status = ACTIVE; + dl_harq->first_rx = 1; + dl_harq->DCINdi = ndi; + } + else if (dl_harq->ack) + dl_harq->status = SCH_IDLE; + break; + case 2: + dl_harq->round = 1; + if (dl_harq->DCINdi != ndi) { + LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); + dl_harq->status = ACTIVE; + dl_harq->first_rx = 1; + dl_harq->DCINdi = ndi; + } + else if (dl_harq->ack) + dl_harq->status = SCH_IDLE; + break; + case 3: + dl_harq->round = 3; + if (dl_harq->DCINdi != ndi) { + LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); + dl_harq->status = ACTIVE; + dl_harq->first_rx = 1; + dl_harq->DCINdi = ndi; + } + else if (dl_harq->ack) + dl_harq->status = SCH_IDLE; + break; + default: + AssertFatal(1==0,"Invalid value for rv %d\n",rv); + } } - else { - dl_harq->round++; - - if (dl_harq->ack) dl_harq->status = SCH_IDLE; - - LOG_D(PHY, "[HARQ-DL-PDSCH harqId : %d] reception of a retransmission \n", harq_pid); - } } diff --git a/openair1/SCHED_NR_UE/harq_nr.h b/openair1/SCHED_NR_UE/harq_nr.h index 47d1de8a11..5586518d7c 100644 --- a/openair1/SCHED_NR_UE/harq_nr.h +++ b/openair1/SCHED_NR_UE/harq_nr.h @@ -120,7 +120,7 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq); @param rnti_type type of rnti @returns retransmission or new transmission */ -void downlink_harq_process(NR_DL_UE_HARQ_t *dlsch, int harq_pid, int ndi, uint8_t rnti_type); +void downlink_harq_process(NR_DL_UE_HARQ_t *dlsch, int harq_pid, int ndi, int rv, uint8_t rnti_type); #undef EXTERN #undef INIT_VARIABLES_HARQ_NR_H From 01de60f95c4e42f3ac95bd9856a82cedd30dd5a9 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 23 Aug 2021 12:14:17 +0200 Subject: [PATCH 164/185] initialization of harq ndi --- openair1/SCHED_NR_UE/harq_nr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 660cfbb910..3065abfdbb 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -308,6 +308,7 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) dl_harq->status = SCH_IDLE; dl_harq->first_rx = 1; dl_harq->round = 0; + dl_harq->DCINdi = 1; dl_harq->ack = DL_ACKNACK_NO_SET; } From e86a48bc1f1d8393e8b89814b36f37d1672220f8 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 23 Aug 2021 14:41:08 +0200 Subject: [PATCH 165/185] fixes --- openair1/SCHED_NR_UE/harq_nr.c | 3 +++ openair1/SIMULATION/NR_PHY/dlsim.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index 3065abfdbb..7bc1f3053b 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -351,6 +351,7 @@ void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, int break; case 1: dl_harq->round = 2; + dl_harq->first_rx = 0; if (dl_harq->DCINdi != ndi) { LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); dl_harq->status = ACTIVE; @@ -362,6 +363,7 @@ void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, int break; case 2: dl_harq->round = 1; + dl_harq->first_rx = 0; if (dl_harq->DCINdi != ndi) { LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); dl_harq->status = ACTIVE; @@ -373,6 +375,7 @@ void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int ndi, int break; case 3: dl_harq->round = 3; + dl_harq->first_rx = 0; if (dl_harq->DCINdi != ndi) { LOG_E(PHY,"Missed previous DCI detections. NDI toggled but rv %d does not correspond to first reception\n",rv); dl_harq->status = ACTIVE; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f082c40fb8..7137dab2f9 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1005,9 +1005,10 @@ int main(int argc, char **argv) UE_harq_process->ack = 0; round = 0; UE_harq_process->round = round; - UE_harq_process->first_tx = 1; + UE_harq_process->first_rx = 1; while ((roundack==0)) { + memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int)); memset(RC.nrmac[0]->cce_list[1][1],0,MAX_NUM_CCE*sizeof(int)); clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); From 6bf28747118928ea8612be368114d5c64d8310fc Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 23 Aug 2021 17:09:25 +0200 Subject: [PATCH 166/185] nr: add T trace for msg4 (rrc setup) --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 220b4a921e..781c3d3b14 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1479,6 +1479,9 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } } + T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti), + T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->tb, harq->tb_size)); + // DL TX request nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; memcpy(tx_req->TLVs[0].value.direct, harq->tb, sizeof(uint8_t) * harq->tb_size); From b4a20d062d6562ad71d378851eebefcb595e828a Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 25 Aug 2021 12:21:18 +0000 Subject: [PATCH 167/185] Fix in rbSize loop --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 89e0d62402..493779225c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1324,7 +1324,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra harq->tb_size = nr_compute_tbs(nr_get_Qm_dl(mcsIndex, mcsTableIdx), nr_get_code_rate_dl(mcsIndex, mcsTableIdx), rbSize, nrOfSymbols, N_PRB_DMRS * N_DMRS_SLOT, 0, tb_scaling,1) >> 3; - } while (rbStart + rbSize < BWPSize && !vrb_map[rbStart + rbSize] && harq->tb_size < ra->mac_pdu_length); + } while (rbSize < BWPSize && harq->tb_size < ra->mac_pdu_length); for (int i = 0; (i < rbSize) && (rbStart <= (BWPSize - rbSize)); i++) { if (vrb_map[rbStart + i]) { From 054c1e53b73db51c80b2dac54d94e6aad19c3406 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 25 Aug 2021 13:49:30 +0000 Subject: [PATCH 168/185] Fix for vrb_map occupation loop --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 493779225c..87a2e8a88b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1326,10 +1326,13 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra rbSize, nrOfSymbols, N_PRB_DMRS * N_DMRS_SLOT, 0, tb_scaling,1) >> 3; } while (rbSize < BWPSize && harq->tb_size < ra->mac_pdu_length); - for (int i = 0; (i < rbSize) && (rbStart <= (BWPSize - rbSize)); i++) { + int i = 0; + while ((i < rbSize) && (rbStart + rbSize <= BWPSize)) { if (vrb_map[rbStart + i]) { - rbStart += i; + rbStart += i+1; i = 0; + } else { + i++; } } From 6df331d80ec05aca315778708ce72914f961ee7b Mon Sep 17 00:00:00 2001 From: hardy Date: Wed, 25 Aug 2021 17:09:03 +0200 Subject: [PATCH 169/185] fixing packet loss thresholds for nsa test for better fail detection --- ci-scripts/xml_files/fr1_nsa_quectel.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/xml_files/fr1_nsa_quectel.xml b/ci-scripts/xml_files/fr1_nsa_quectel.xml index 7ec3a5f140..6c11a66d91 100644 --- a/ci-scripts/xml_files/fr1_nsa_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel.xml @@ -97,7 +97,7 @@ Ping: 20pings in 20sec idefix -c 20 - 50 + 1 @@ -105,7 +105,7 @@ Ping: 100pings in 20sec idefix -c 100 -i 0.2 - 50 + 1 @@ -114,7 +114,7 @@ -u -b 20M -t 60 DL idefix - 50 + 3 single-ue @@ -124,7 +124,7 @@ -u -b 3M -t 60 UL idefix - 50 + 1 single-ue From e8c74760467136f426c68c1847de948b07f22762 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 26 Aug 2021 13:23:41 +0200 Subject: [PATCH 170/185] fix to allow traffic to be put in msg3 --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 6 ++++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 6d7945a380..0e1f83863a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -952,12 +952,14 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in } LOG_D(NR_MAC,"Flipping NDI for harq_id %d (Msg3)\n",ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator); mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; - mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = 0; + mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = 0; } else { if ((mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator || mac->first_ul_tx[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id]==1) && - ((get_softmodem_params()->phy_test == 1) || (ra->ra_state == RA_SUCCEEDED))){ + ((get_softmodem_params()->phy_test == 1) || + (ra->ra_state == RA_SUCCEEDED) || + (ra->ra_state == WAIT_RAR && ra->cfra))){ // Getting IP traffic to be transmitted nr_ue_get_sdu(mod_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 57867df45f..6a17cb4879 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -487,7 +487,7 @@ void nr_csi_meas_reporting(int Mod_idP, // preparation is done in first slot of tdd period if (frame % (period / n_slots_frame) != offset / n_slots_frame) continue; - LOG_I(MAC, "CSI reporting in frame %d slot %d\n", frame, sched_slot); + LOG_D(MAC, "CSI reporting in frame %d slot %d\n", frame, sched_slot); const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 @@ -986,7 +986,7 @@ void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig, // verify if report with current id has been scheduled for this frame and slot if ((n_slots_frame*frame + slot - offset)%period == 0) { reportQuantity_type = UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type; - LOG_I(MAC,"SFN/SF:%d/%d reportQuantity type = %d\n",frame,slot,reportQuantity_type); + LOG_D(MAC,"SFN/SF:%d/%d reportQuantity type = %d\n",frame,slot,reportQuantity_type); switch(reportQuantity_type){ case NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP: evaluate_rsrp_report(UE_info,sched_ctrl,UE_id,csi_report_id,payload,&cumul_bits,reportQuantity_type); From d0c1bc43405777e501fca64d627acd6e193a86ce Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 27 Aug 2021 12:42:25 +0200 Subject: [PATCH 171/185] skip dlsch mac pdu processing when crc fails --- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 435d7e8d30..b5c2f666a2 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -79,13 +79,13 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t // L2 Abstraction Layer // Note: sdu should always be processed because data and timing advance updates are transmitted by the UE -int8_t handle_dlsch (nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ +int8_t handle_dlsch(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ update_harq_status(dl_info, pdu_id); - nr_ue_send_sdu(dl_info, ul_time_alignment, pdu_id); + if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack) + nr_ue_send_sdu(dl_info, ul_time_alignment, pdu_id); return 0; - } int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ From e93545bc084b8d4ab34d7779255e30a394b7caba Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 27 Aug 2021 12:58:53 +0200 Subject: [PATCH 172/185] formatting --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 470 +++++++++---------- 1 file changed, 230 insertions(+), 240 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index b3ca9bdec2..11a8f1fea4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3130,248 +3130,238 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, LOG_D(MAC, "In %s [%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, frameP, slot, pdu_id, pdu_len, dl_info->rx_ind->number_pdus); - while (!done && pdu_len > 0){ - mac_ce_len = 0x0000; - mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct - mac_sdu_len = 0x0000; - rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; + while (!done && pdu_len > 0){ + mac_ce_len = 0x0000; + mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct + mac_sdu_len = 0x0000; + rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; - LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", rx_lcid, pdu_len); - switch(rx_lcid){ - // MAC CE - - case DL_SCH_LCID_CCCH: - // MSG4 RRC Setup 38.331 - // variable length - if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ - mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8) - | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff); - mac_subheader_len = 3; - } else { - mac_sdu_len = ((NR_MAC_SUBHEADER_SHORT *) pduP)->L; - mac_subheader_len = 2; - } - - // Check if it is a valid CCCH message, we get all 00's messages very often - int i = 0; - for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) { - if(pduP[i] != 0) { - break; - } - } - if (i == (mac_subheader_len+mac_sdu_len)) { - LOG_D(NR_MAC, "%s() Invalid CCCH message!, pdu_len: %d\n", __func__, pdu_len); - done = 1; - break; - } - - if ( mac_sdu_len > 0 ) { - LOG_D(NR_MAC,"DL_SCH_LCID_CCCH (e.g. RRCSetup) with payload len %d\n", mac_sdu_len); - for (int i = 0; i < mac_subheader_len; i++) { - LOG_D(NR_MAC, "MAC header %d: 0x%x\n", i, pduP[i]); - } - for (int i = 0; i < mac_sdu_len; i++) { - LOG_D(NR_MAC, "%d: 0x%x\n", i, pduP[mac_subheader_len + i]); - } - nr_mac_rrc_data_ind_ue(module_idP, CC_id, gNB_index, frameP, 0, mac->crnti, CCCH, pduP+mac_subheader_len, mac_sdu_len); - } - break; - - case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH: - - // 38.321 Ch6.1.3.14 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; - mac_subheader_len = 3; - } - break; - case DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL: - // 38.321 Ch6.1.3.13 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; - mac_subheader_len = 3; - } - break; - case DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT: - // 38.321 Ch6.1.3.12 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; - mac_subheader_len = 3; - } - break; - case DL_SCH_LCID_SP_SRS_ACTIVATION: - // 38.321 Ch6.1.3.17 - // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; - mac_subheader_len = 3; - } - break; - - case DL_SCH_LCID_RECOMMENDED_BITRATE: - // 38.321 Ch6.1.3.20 - mac_ce_len = 2; - break; - case DL_SCH_LCID_SP_ZP_CSI_RS_RES_SET_ACT: - // 38.321 Ch6.1.3.19 - mac_ce_len = 2; - break; - case DL_SCH_LCID_PUCCH_SPATIAL_RELATION_ACT: - // 38.321 Ch6.1.3.18 - mac_ce_len = 3; - break; - case DL_SCH_LCID_SP_CSI_REP_PUCCH_ACT: - // 38.321 Ch6.1.3.16 - mac_ce_len = 2; - break; - case DL_SCH_LCID_TCI_STATE_IND_UE_SPEC_PDCCH: - // 38.321 Ch6.1.3.15 - mac_ce_len = 2; - break; - case DL_SCH_LCID_DUPLICATION_ACT: - // 38.321 Ch6.1.3.11 - mac_ce_len = 1; - break; - case DL_SCH_LCID_SCell_ACT_4_OCT: - // 38.321 Ch6.1.3.10 - mac_ce_len = 4; - break; - case DL_SCH_LCID_SCell_ACT_1_OCT: - // 38.321 Ch6.1.3.10 - mac_ce_len = 1; - break; - case DL_SCH_LCID_L_DRX: - // 38.321 Ch6.1.3.6 - // fixed length but not yet specify. - mac_ce_len = 0; - break; - case DL_SCH_LCID_DRX: - // 38.321 Ch6.1.3.5 - // fixed length but not yet specify. - mac_ce_len = 0; - break; - case DL_SCH_LCID_TA_COMMAND: - // 38.321 Ch6.1.3.4 - mac_ce_len = 1; - - /*uint8_t ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; - uint8_t tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID;*/ - - ul_time_alignment->apply_ta = 1; - ul_time_alignment->ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; - ul_time_alignment->tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID; - - /* - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]); - #endif - */ - - LOG_I(MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d\n", frameP, slot, ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); - - break; - case DL_SCH_LCID_CON_RES_ID: - // Clause 5.1.5 and 6.1.3.3 of 3GPP TS 38.321 version 16.2.1 Release 16 - // MAC Header: 1 byte (R/R/LCID) - // MAC SDU: 6 bytes (UE Contention Resolution Identity) - mac_ce_len = 6; - - if(ra->ra_state == WAIT_CONTENTION_RESOLUTION) { - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", - module_idP, frameP, pduP[1], pduP[2], pduP[3], pduP[4], pduP[5], pduP[6]); - - bool ra_success = true; - for(int i = 0; icont_res_id[i] != pduP[i+1]) { - ra_success = false; - break; - } - } - - if ( (ra->RA_active == 1) && ra_success) { - nr_ra_succeeded(module_idP, frameP, slot); - } else if (!ra_success){ - // TODO: Handle failure of RA procedure @ MAC layer - // nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure - ra->ra_state = RA_UE_IDLE; - ra->RA_active = 0; - } - } - - break; - case DL_SCH_LCID_PADDING: - done = 1; - // end of MAC PDU, can ignore the rest. - break; - - // MAC SDU - - case DL_SCH_LCID_DCCH: - // check if LCID is valid at current time. - - case DL_SCH_LCID_DCCH1: - // check if LCID is valid at current time. - - default: - // check if LCID is valid at current time. - if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ - //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; - mac_subheader_len = 3; - mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8) - | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff); - - } else { - mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; - mac_subheader_len = 2; - } - - LOG_D(MAC, "[UE %d] Frame %d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, gNB_index, mac_sdu_len); - - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); - - for (i = 0; i < 32; i++) - LOG_T(MAC, "%x.", (pduP + mac_subheader_len)[i]); - - LOG_T(MAC, "\n"); - #endif - -// if (IS_SOFTMODEM_NOS1){ - if (rx_lcid < NB_RB_MAX && rx_lcid >= DL_SCH_LCID_DCCH) { - - mac_rlc_data_ind(module_idP, - mac->crnti, - gNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pduP + mac_subheader_len), - mac_sdu_len, - 1, - NULL); - } else { - LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, gNB_index); - } -// } - - break; + LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", rx_lcid, pdu_len); + switch(rx_lcid){ + // MAC CE + case DL_SCH_LCID_CCCH: + // MSG4 RRC Setup 38.331 + // variable length + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8) + | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff); + mac_subheader_len = 3; + } else { + mac_sdu_len = ((NR_MAC_SUBHEADER_SHORT *) pduP)->L; + mac_subheader_len = 2; } - pduP += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); - pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); - if (pdu_len < 0) - LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", module_idP, frameP, slot, pdu_len); + + // Check if it is a valid CCCH message, we get all 00's messages very often + int i = 0; + for(i=0; i<(mac_subheader_len+mac_sdu_len); i++) { + if(pduP[i] != 0) { + break; + } + } + if (i == (mac_subheader_len+mac_sdu_len)) { + LOG_D(NR_MAC, "%s() Invalid CCCH message!, pdu_len: %d\n", __func__, pdu_len); + done = 1; + break; + } + + if ( mac_sdu_len > 0 ) { + LOG_D(NR_MAC,"DL_SCH_LCID_CCCH (e.g. RRCSetup) with payload len %d\n", mac_sdu_len); + for (int i = 0; i < mac_subheader_len; i++) { + LOG_D(NR_MAC, "MAC header %d: 0x%x\n", i, pduP[i]); + } + for (int i = 0; i < mac_sdu_len; i++) { + LOG_D(NR_MAC, "%d: 0x%x\n", i, pduP[mac_subheader_len + i]); + } + nr_mac_rrc_data_ind_ue(module_idP, CC_id, gNB_index, frameP, 0, mac->crnti, CCCH, pduP+mac_subheader_len, mac_sdu_len); + } + break; + case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH: + + // 38.321 Ch6.1.3.14 + // varialbe length + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + } + break; + case DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL: + // 38.321 Ch6.1.3.13 + // varialbe length + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + } + break; + case DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT: + // 38.321 Ch6.1.3.12 + // varialbe length + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + } + break; + case DL_SCH_LCID_SP_SRS_ACTIVATION: + // 38.321 Ch6.1.3.17 + // varialbe length + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + } + break; + case DL_SCH_LCID_RECOMMENDED_BITRATE: + // 38.321 Ch6.1.3.20 + mac_ce_len = 2; + break; + case DL_SCH_LCID_SP_ZP_CSI_RS_RES_SET_ACT: + // 38.321 Ch6.1.3.19 + mac_ce_len = 2; + break; + case DL_SCH_LCID_PUCCH_SPATIAL_RELATION_ACT: + // 38.321 Ch6.1.3.18 + mac_ce_len = 3; + break; + case DL_SCH_LCID_SP_CSI_REP_PUCCH_ACT: + // 38.321 Ch6.1.3.16 + mac_ce_len = 2; + break; + case DL_SCH_LCID_TCI_STATE_IND_UE_SPEC_PDCCH: + // 38.321 Ch6.1.3.15 + mac_ce_len = 2; + break; + case DL_SCH_LCID_DUPLICATION_ACT: + // 38.321 Ch6.1.3.11 + mac_ce_len = 1; + break; + case DL_SCH_LCID_SCell_ACT_4_OCT: + // 38.321 Ch6.1.3.10 + mac_ce_len = 4; + break; + case DL_SCH_LCID_SCell_ACT_1_OCT: + // 38.321 Ch6.1.3.10 + mac_ce_len = 1; + break; + case DL_SCH_LCID_L_DRX: + // 38.321 Ch6.1.3.6 + // fixed length but not yet specify. + mac_ce_len = 0; + break; + case DL_SCH_LCID_DRX: + // 38.321 Ch6.1.3.5 + // fixed length but not yet specify. + mac_ce_len = 0; + break; + case DL_SCH_LCID_TA_COMMAND: + // 38.321 Ch6.1.3.4 + mac_ce_len = 1; + + /*uint8_t ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + uint8_t tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID;*/ + + ul_time_alignment->apply_ta = 1; + ul_time_alignment->ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + ul_time_alignment->tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID; + + /* + #ifdef DEBUG_HEADER_PARSING + LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]); + #endif + */ + + LOG_I(MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d\n", frameP, slot, ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); + + break; + case DL_SCH_LCID_CON_RES_ID: + // Clause 5.1.5 and 6.1.3.3 of 3GPP TS 38.321 version 16.2.1 Release 16 + // MAC Header: 1 byte (R/R/LCID) + // MAC SDU: 6 bytes (UE Contention Resolution Identity) + mac_ce_len = 6; + + if(ra->ra_state == WAIT_CONTENTION_RESOLUTION) { + LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", + module_idP, frameP, pduP[1], pduP[2], pduP[3], pduP[4], pduP[5], pduP[6]); + + bool ra_success = true; + for(int i = 0; icont_res_id[i] != pduP[i+1]) { + ra_success = false; + break; + } + } + + if ( (ra->RA_active == 1) && ra_success) { + nr_ra_succeeded(module_idP, frameP, slot); + } else if (!ra_success){ + // TODO: Handle failure of RA procedure @ MAC layer + // nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure + ra->ra_state = RA_UE_IDLE; + ra->RA_active = 0; + } + } + break; + case DL_SCH_LCID_PADDING: + done = 1; + // end of MAC PDU, can ignore the rest. + break; + // MAC SDU + case DL_SCH_LCID_DCCH: + // check if LCID is valid at current time. + case DL_SCH_LCID_DCCH1: + // check if LCID is valid at current time. + default: + // check if LCID is valid at current time. + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; + mac_subheader_len = 3; + mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8) + | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff); + + } else { + mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; + mac_subheader_len = 2; + } + + LOG_D(MAC, "[UE %d] Frame %d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, gNB_index, mac_sdu_len); + + #if defined(ENABLE_MAC_PAYLOAD_DEBUG) + LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); + + for (i = 0; i < 32; i++) + LOG_T(MAC, "%x.", (pduP + mac_subheader_len)[i]); + + LOG_T(MAC, "\n"); + #endif + + if (rx_lcid < NB_RB_MAX && rx_lcid >= DL_SCH_LCID_DCCH) { + + mac_rlc_data_ind(module_idP, + mac->crnti, + gNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pduP + mac_subheader_len), + mac_sdu_len, + 1, + NULL); + } else { + LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, gNB_index); + } + + break; + } + pduP += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); + pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); + if (pdu_len < 0) + LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", module_idP, frameP, slot, pdu_len); } } From 309a8c3e3e9151993a00673ab46818c379389302 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Mon, 30 Aug 2021 14:31:22 +0200 Subject: [PATCH 173/185] CI: -- Reduce required BW test in 4G RF sim Docker: -- Made the "Thread Parallel Config" a flexible parameter default is SINGLE_THREAD -- Clean Up on some Docker file about pyyaml Signed-off-by: Raphael Defosseux --- ci-scripts/xml_files/container_4g_rfsim.xml | 4 ++-- docker/Dockerfile.lteUE.rhel8.2 | 4 +--- docker/Dockerfile.lteUE.ubuntu18 | 4 +--- docker/scripts/enb_entrypoint.sh | 1 + docker/scripts/enb_parameters.yaml | 16 ++++++++++++++++ docker/scripts/gnb_entrypoint.sh | 1 + docker/scripts/gnb_parameters.yaml | 4 ++++ 7 files changed, 26 insertions(+), 8 deletions(-) diff --git a/ci-scripts/xml_files/container_4g_rfsim.xml b/ci-scripts/xml_files/container_4g_rfsim.xml index f342c3f5ce..5f3e5320af 100644 --- a/ci-scripts/xml_files/container_4g_rfsim.xml +++ b/ci-scripts/xml_files/container_4g_rfsim.xml @@ -109,7 +109,7 @@ rfsim4g-oai-lte-ue0 rfsim4g-trf-gen -B 12.0.0.2 -u -i 1 -s - -c 12.0.0.2 -u -i 1 -t 30 -b 4M + -c 12.0.0.2 -u -i 1 -t 30 -b 2M @@ -118,7 +118,7 @@ rfsim4g-trf-gen rfsim4g-oai-lte-ue0 -u -i 1 -s - -B 12.0.0.2 -c 192.168.61.11 -u -i 1 -t 30 -b 2M + -B 12.0.0.2 -c 192.168.61.11 -u -i 1 -t 30 -b 1M diff --git a/docker/Dockerfile.lteUE.rhel8.2 b/docker/Dockerfile.lteUE.rhel8.2 index 2d540876e3..936780297a 100644 --- a/docker/Dockerfile.lteUE.rhel8.2 +++ b/docker/Dockerfile.lteUE.rhel8.2 @@ -37,9 +37,7 @@ RUN /bin/sh oaienv && \ mkdir -p log && \ ./build_oai --UE --ninja -w USRP --verbose-ci -RUN yum install -y python3-pip && \ - pip3 install --ignore-installed pyyaml && \ - python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_parameters.yaml && \ +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_parameters.yaml && \ python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_sim_parameters.yaml #start from scratch for target executable diff --git a/docker/Dockerfile.lteUE.ubuntu18 b/docker/Dockerfile.lteUE.ubuntu18 index c6a70a0b50..34cbe651ad 100644 --- a/docker/Dockerfile.lteUE.ubuntu18 +++ b/docker/Dockerfile.lteUE.ubuntu18 @@ -37,9 +37,7 @@ RUN /bin/sh oaienv && \ mkdir -p log && \ ./build_oai --UE --ninja -w USRP --verbose-ci -RUN apt-get install -y python3-pip && \ - pip3 install --ignore-installed pyyaml && \ - python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_parameters.yaml && \ +RUN python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_parameters.yaml && \ python3 ./docker/scripts/generateTemplate.py ./docker/scripts/lte_ue_sim_parameters.yaml #start from scratch for target executable diff --git a/docker/scripts/enb_entrypoint.sh b/docker/scripts/enb_entrypoint.sh index 4ac86ef1b7..2e8886e855 100755 --- a/docker/scripts/enb_entrypoint.sh +++ b/docker/scripts/enb_entrypoint.sh @@ -6,6 +6,7 @@ PREFIX=/opt/oai-enb RRC_INACTIVITY_THRESHOLD=${RRC_INACTIVITY_THRESHOLD:-0} ENABLE_MEASUREMENT_REPORTS=${ENABLE_MEASUREMENT_REPORTS:-no} ENABLE_X2=${ENABLE_X2:-no} +THREAD_PARALLEL_CONFIG=${THREAD_PARALLEL_CONFIG:-PARALLEL_SINGLE_THREAD} # Based another env var, pick one template to use if [[ -v USE_FDD_CU ]]; then ln -s $PREFIX/etc/cu.fdd.conf $PREFIX/etc/enb.conf; fi diff --git a/docker/scripts/enb_parameters.yaml b/docker/scripts/enb_parameters.yaml index 58715a7152..07bba4479b 100644 --- a/docker/scripts/enb_parameters.yaml +++ b/docker/scripts/enb_parameters.yaml @@ -98,6 +98,8 @@ env: "@NID_CELL@" - key: N_RB_DL env: "@NB_PRB@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" - filePrefix: rru.fdd outputfilename: "rru.fdd.conf" @@ -110,6 +112,8 @@ env: "@RRU_LOCAL_IP_ADDRESS@" - key: bands env: "@UTRA_BAND_ID@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" - filePrefix: rru.tdd outputfilename: "rru.tdd.conf" @@ -122,6 +126,8 @@ env: "@RRU_LOCAL_IP_ADDRESS@" - key: bands env: "@UTRA_BAND_ID@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" - filePrefix: enb.band7.tm1.fr1.25PRB.usrpb210.conf outputfilename: "enb.fdd.conf" @@ -171,6 +177,8 @@ env: "@FLEXRAN_INTERFACE_NAME@" - key: FLEXRAN_IPV4_ADDRESS env: "@FLEXRAN_IPV4_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" - filePrefix: enb.band40.tm1.25PRB.FairScheduler.usrpb210 outputfilename: "enb.tdd.conf" @@ -208,6 +216,8 @@ env: "@F1_CU_IP_ADDRESS@" - key: ENB_IPV4_ADDRESS_FOR_X2C env: "@F1_CU_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" - filePrefix: "rcc.band7.tm1.nfapi" outputfilename: "rcc.nfapi.fdd.conf" @@ -251,6 +261,8 @@ env: "@F1_CU_IP_ADDRESS@" - key: ENB_IPV4_ADDRESS_FOR_X2C env: "@F1_CU_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" - filePrefix: "rcc.band7.tm1.if4p5.lo.25PRB" outputfilename: "rcc.if4p5.fdd.conf" @@ -294,6 +306,8 @@ env: "@IF4P5_RRU_IP_ADDRESS@" - key: local_address env: "@IF4P5_RCC_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" - filePrefix: "rcc.band40.tm1.25PRB" outputfilename: "rcc.if4p5.tdd.conf" @@ -337,4 +351,6 @@ env: "@IF4P5_RRU_IP_ADDRESS@" - key: local_address env: "@IF4P5_RCC_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" diff --git a/docker/scripts/gnb_entrypoint.sh b/docker/scripts/gnb_entrypoint.sh index 6d3d63629f..678ec6cb1b 100755 --- a/docker/scripts/gnb_entrypoint.sh +++ b/docker/scripts/gnb_entrypoint.sh @@ -4,6 +4,7 @@ set -euo pipefail PREFIX=/opt/oai-gnb ENABLE_X2=${ENABLE_X2:-yes} +THREAD_PARALLEL_CONFIG=${THREAD_PARALLEL_CONFIG:-PARALLEL_SINGLE_THREAD} # Based another env var, pick one template to use if [[ -v USE_NSA_TDD_MONO ]]; then ln -s $PREFIX/etc/gnb.nsa.tdd.conf $PREFIX/etc/gnb.conf; fi diff --git a/docker/scripts/gnb_parameters.yaml b/docker/scripts/gnb_parameters.yaml index a13d0d3677..ac5a6cb971 100644 --- a/docker/scripts/gnb_parameters.yaml +++ b/docker/scripts/gnb_parameters.yaml @@ -61,6 +61,8 @@ env: "@FLEXRAN_INTERFACE_NAME@" - key: FLEXRAN_IPV4_ADDRESS env: "@FLEXRAN_IPV4_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" - filePrefix: gnb.band78.sa.fr1.106PRB.usrpn310.conf outputfilename: "gnb.sa.tdd.conf" @@ -89,4 +91,6 @@ env: "@GNB_NGU_IF_NAME@" - key: GNB_IPV4_ADDRESS_FOR_NGU env: "@GNB_NGU_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" From 3bd6309e2eeec154bb6b5cd84ef342e296917dad Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Mon, 30 Aug 2021 16:36:40 +0200 Subject: [PATCH 174/185] fix(test): cosmetics in 4G LTE RF sim test Signed-off-by: Raphael Defosseux --- ci-scripts/xml_files/container_4g_rfsim.xml | 5 ++--- ci-scripts/xml_files/container_4g_rfsim_down.xml | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ci-scripts/xml_files/container_4g_rfsim.xml b/ci-scripts/xml_files/container_4g_rfsim.xml index 5f3e5320af..5430b2b056 100644 --- a/ci-scripts/xml_files/container_4g_rfsim.xml +++ b/ci-scripts/xml_files/container_4g_rfsim.xml @@ -21,10 +21,9 @@ --> - rfsim-4gnr - Testing 4G NR RF sim in containers + rfsim-4glte + Testing 4G LTE RF sim in containers wrench - 4 100011 000011 diff --git a/ci-scripts/xml_files/container_4g_rfsim_down.xml b/ci-scripts/xml_files/container_4g_rfsim_down.xml index cce2b32cf3..dee516d924 100644 --- a/ci-scripts/xml_files/container_4g_rfsim_down.xml +++ b/ci-scripts/xml_files/container_4g_rfsim_down.xml @@ -21,9 +21,9 @@ --> - rfsim-4gnr - Testing 4G NR RF sim in containers - wrench + rfsim-4glte-down + CleanUp 4G RF + trash 100011 From 81d818cf680cf717b059b752b3673ff981db6c49 Mon Sep 17 00:00:00 2001 From: hardy Date: Tue, 31 Aug 2021 12:41:55 +0200 Subject: [PATCH 175/185] improve packet loss mismatch detection --- ci-scripts/cls_oaicitest.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 15b28cbe99..f1ab8c106f 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -2005,6 +2005,7 @@ class OaiCiTest(): curr_br = curr_br * 1000 * 1000 br_sum = curr_br + br_sum ji_sum = float(ji[0]) + ji_sum + if (row_idx > 0): br_sum = br_sum / row_idx ji_sum = ji_sum / row_idx @@ -2025,10 +2026,12 @@ class OaiCiTest(): pl = float(100 * pl_sum / ps_sum) packetloss = '%2.1f ' % (pl) packetloss += '%' - else: - packetloss = 'unknown' + if float(pl) > float(self.iperf_packetloss_threshold): + pal_too_high_msg = 'Packet Loss too high : actual = '+packetloss+', target = '+self.iperf_packetloss_threshold+'%\n' + else: + pal_too_high_msg='' lock.acquire() - if (br_loss < 90): + if (br_loss < 90) or (float(pl) > float(self.iperf_packetloss_threshold)): statusQueue.put(1) else: statusQueue.put(0) @@ -2039,13 +2042,14 @@ class OaiCiTest(): brl_msg = 'Bitrate Perf: ' + bitperf jit_msg = 'Jitter : ' + jitter pal_msg = 'Packet Loss : ' + packetloss - statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n') + statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n' + pal_too_high_msg + '\n') logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + pal_too_high_msg + '\u001B[0m') lock.release() else: self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') @@ -2705,7 +2709,7 @@ class OaiCiTest(): if (status_queue.empty()): HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfaUE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC,InfraUE) else: iperf_status = True iperf_noperf = False From 854f7a769c9e793126c5f7020e988bcbe165446e Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 1 Sep 2021 06:59:07 +0200 Subject: [PATCH 176/185] fixing missed initialization --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index ad525bf29a..1736d68e65 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -487,8 +487,8 @@ bool allocate_dl_retransmission(module_id_t module_id, while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize]) rbSize++; NR_pdsch_semi_static_t temp_ps; - nr_set_pdsch_semi_static( - scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, &temp_ps); + temp_ps.nrOfLayers = 1; + nr_set_pdsch_semi_static(scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, &temp_ps); uint32_t new_tbs; uint16_t new_rbSize; bool success = nr_find_nb_rb(retInfo->Qm, From d360113cfa2895e2b99aa68bcf477fd4b7306c81 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 1 Sep 2021 11:29:32 +0200 Subject: [PATCH 177/185] comment out end_configmodule meanwhile someone verify all parameters that should have PARAMFLAG_NOFREE --- executables/nr-softmodem.c | 3 ++- targets/RT/USER/lte-uesoftmodem.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index b855418d64..1b33667b13 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -823,7 +823,8 @@ int main( int argc, char **argv ) { } printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); - end_configmodule(); + // We have to set PARAMFLAG_NOFREE on right paramters before re-enabling end_configmodule() + //end_configmodule(); printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); // wait for end of program printf("TYPE TO TERMINATE\n"); diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index 026e6d4a60..25bbef0bc6 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -757,6 +757,7 @@ int main( int argc, char **argv ) { printf("sync sent\n"); /* printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); + We have to set properly PARAMFLAG_NOFREE end_configmodule(); printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__); */ From 592d99b5bcdc867371fa1747c887b597eb37f034 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 3 Sep 2021 10:27:33 +0200 Subject: [PATCH 178/185] fix(enb): start_background_system was not called in noS1 mode Signed-off-by: Raphael Defosseux --- common/utils/system.c | 4 ++++ targets/RT/USER/lte-softmodem.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/common/utils/system.c b/common/utils/system.c index d8b66c51d3..38d1c1d7ad 100644 --- a/common/utils/system.c +++ b/common/utils/system.c @@ -209,6 +209,10 @@ int background_system(char *command) { void start_background_system(void) { int p[2]; pid_t son; + + if (module_initialized == 1) + return; + module_initialized = 1; if (pipe(p) == -1) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index f9ff03e422..a67b58d61a 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -525,6 +525,8 @@ int main ( int argc, char **argv ) int ru_id; int node_type = ngran_eNB; + start_background_system(); + if ( load_configmodule(argc,argv,0) == NULL) { exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); } From d9d4b91185cac594d9bf778a0da51a74534f87c1 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 3 Sep 2021 13:07:56 +0200 Subject: [PATCH 179/185] fix(NAS): remove compilation warning Signed-off-by: Raphael Defosseux --- openair2/RRC/NAS/nas_config.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openair2/RRC/NAS/nas_config.c b/openair2/RRC/NAS/nas_config.c index 22a7ef2711..31ca8f9eb8 100644 --- a/openair2/RRC/NAS/nas_config.c +++ b/openair2/RRC/NAS/nas_config.c @@ -355,6 +355,11 @@ int nas_config(int interface_id, int thirdOctet, int fourthOctet, char *ifname) UE_NAS_USE_TUN ? "oaitun_ue" : "oip", interface_id, interface_id - 1 + 10000); + if (res < 0) { + LOG_E(OIP,"Could not create ip rule/route commands string\n"); + return res; + } + background_system(command_line); return returnValue; From 58904eaab8947c790a66678508bb4edaf6f877eb Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 7 Sep 2021 13:08:14 +0200 Subject: [PATCH 180/185] cleanup: replace "eNB" by "gNB" as it should be --- openair2/LAYER2/nr_rlc/tests/test.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/tests/test.c b/openair2/LAYER2/nr_rlc/tests/test.c index 742e79ca2c..bfde8b9fad 100644 --- a/openair2/LAYER2/nr_rlc/tests/test.c +++ b/openair2/LAYER2/nr_rlc/tests/test.c @@ -22,13 +22,13 @@ * create the UE RLC AM entity with given parameters * * GNB_UM - * create the eNB RLC UM entity with given parameters + * create the gNB RLC UM entity with given parameters * * UE_UM * create the UE RLC UM entity with given parameters * * GNB_TM - * create the eNB RLC TM entity with given parameters + * create the gNB RLC TM entity with given parameters * * UE_UM * create the UE RLC TM entity with given parameters @@ -39,7 +39,7 @@ * You must end your test definition with a line 'TIME, -1'. * * GNB_SDU - * send an SDU to eNB with id and size + * send an SDU to gNB with id and size * the SDU is [00 01 ... ff 01 ...] * (ie. start byte is 00 then we increment for each byte, loop if needed) * @@ -47,10 +47,10 @@ * same as GNB_SDU but the SDU is sent to the UE * * GNB_PDU <'size' bytes> - * send a custom PDU from eNB to UE (eNB does not see this PDU at all) + * send a custom PDU from gNB to UE (gNB does not see this PDU at all) * * UE_PDU <'size' bytes> - * send a custom PDU from UE to eNB (UE does not see this PDU at all) + * send a custom PDU from UE to gNB (UE does not see this PDU at all) * * GNB_PDU_SIZE * set 'gnb_pdu_size' @@ -70,7 +70,7 @@ * that the test must fail (ie. exit with non zero, crash not allowed) * * GNB_BUFFER_STATUS - * call buffer_status for eNB and print result + * call buffer_status for gNB and print result * * UE_BUFFER_STATUS * call buffer_status for UE and print result @@ -82,7 +82,7 @@ * discards given SDU * * RE_ESTABLISH - * re-establish both eNB and UE + * re-establish both gNB and UE */ enum action { @@ -368,7 +368,7 @@ int test_main(void) pos += 2; break; case RE_ESTABLISH: - printf("TEST: %d: re-establish eNB and UE\n", i); + printf("TEST: %d: re-establish gNB and UE\n", i); gnb->reestablishment(gnb); ue->reestablishment(ue); pos++; From 36bae67eef91bf21293214e527047c25a40896b7 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 7 Sep 2021 13:16:39 +0200 Subject: [PATCH 181/185] nr-rlc: bugfix: copy correct part of PDUs in case of segmentation --- openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c | 2 +- openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c | 2 +- openair2/LAYER2/nr_rlc/tests/run_tests.sh | 2 +- openair2/LAYER2/nr_rlc/tests/test16.h | 19 +++++++++++++++++++ openair2/LAYER2/nr_rlc/tests/test16.txt.gz | Bin 0 -> 168 bytes openair2/LAYER2/nr_rlc/tests/test17.h | 18 ++++++++++++++++++ openair2/LAYER2/nr_rlc/tests/test17.txt.gz | Bin 0 -> 148 bytes 7 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 openair2/LAYER2/nr_rlc/tests/test16.h create mode 100644 openair2/LAYER2/nr_rlc/tests/test16.txt.gz create mode 100644 openair2/LAYER2/nr_rlc/tests/test17.h create mode 100644 openair2/LAYER2/nr_rlc/tests/test17.txt.gz diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 08f5b11c23..8db5ce31ad 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -218,7 +218,7 @@ static void reassemble_and_deliver(nr_rlc_entity_am_t *entity, int sn) bad_sdu = 1; } if (!bad_sdu && len > 0) { - memcpy(sdu + so, pdu->data, len); + memcpy(sdu + so, pdu->data + so - pdu->so, len); so += len; } free(pdu->data); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c index f967c3c543..71173eee5a 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_um.c @@ -148,7 +148,7 @@ static void reassemble_and_deliver(nr_rlc_entity_um_t *entity, int sn) bad_sdu = 1; } if (!bad_sdu && len > 0) { - memcpy(sdu + so, pdu->data, len); + memcpy(sdu + so, pdu->data + so - pdu->so, len); so += len; } free(pdu->data); diff --git a/openair2/LAYER2/nr_rlc/tests/run_tests.sh b/openair2/LAYER2/nr_rlc/tests/run_tests.sh index a98f6b5d0f..7ca4798861 100755 --- a/openair2/LAYER2/nr_rlc/tests/run_tests.sh +++ b/openair2/LAYER2/nr_rlc/tests/run_tests.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_count=15 +test_count=17 for i in `seq $test_count` do diff --git a/openair2/LAYER2/nr_rlc/tests/test16.h b/openair2/LAYER2/nr_rlc/tests/test16.h new file mode 100644 index 0000000000..92f9923809 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/test16.h @@ -0,0 +1,19 @@ +/* + * am test (SN field size 18): + * there was a bug when we receive a full PDU after receiving only the + * beginning of it; the data was copied at the end but from the start of the + * full PDU instead of the correct offset. This test captures this case. + * Gnb sends the start of a PDU then the full PDU. That is the SDU is + * [00 .. 09]. First gnb sends [00 .. 08] then it sends [00 .. 09]. + */ + +TIME, 1, + GNB_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + UE_AM, 100000, 100000, 45, 35, 0, -1, -1, 8, 18, + GNB_PDU_SIZE, 12, + UE_PDU_SIZE, 20, + GNB_PDU, 12, 0x90, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +TIME, 2, + GNB_PDU_SIZE, 20, + GNB_PDU, 13, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, +TIME, -1 diff --git a/openair2/LAYER2/nr_rlc/tests/test16.txt.gz b/openair2/LAYER2/nr_rlc/tests/test16.txt.gz new file mode 100644 index 0000000000000000000000000000000000000000..74b19724aab10fcde721e98fa8e7565616eb133e GIT binary patch literal 168 zcmV;Z09XGXiwFpENH<{u19W9`bTKwAba-?C3vmq&u~H~5Nh~Vi3IVg-{hX{646PKB zON&eLa}@$yLV@y`RjCSwMpg>Z3YG>625@AkU|^(RV60$ZqF`XEU|^=Hc7$25@uMaE7(;jsX3WtsYMFGE}>Af41h)vZ356W>8W|CMTsS;@dYWR WQ1^hH19gZ=EEfRSWj{L<0RR98);?kY literal 0 HcmV?d00001 diff --git a/openair2/LAYER2/nr_rlc/tests/test17.h b/openair2/LAYER2/nr_rlc/tests/test17.h new file mode 100644 index 0000000000..3da9fcc6e5 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/test17.h @@ -0,0 +1,18 @@ +/* + * um test (SN field size 12): + * same problem as for test16, but we test by sending [00 .. 08] then + * [02 .. 09] (they overlap, the full SDU is [00 .. 09]), which probably + * never occurs in practice but triggers the bug. Doing as for test16 does + * not trigger the bug. + */ + +TIME, 1, + GNB_UM, 100000, 100000, 35, 12, + UE_UM, 100000, 100000, 35, 12, + GNB_PDU_SIZE, 8, + UE_PDU_SIZE, 20, + GNB_PDU, 11, 0x40, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +TIME, 2, + GNB_PDU_SIZE, 20, + GNB_PDU, 12, 0x80, 0x00, 0x00, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, +TIME, -1 diff --git a/openair2/LAYER2/nr_rlc/tests/test17.txt.gz b/openair2/LAYER2/nr_rlc/tests/test17.txt.gz new file mode 100644 index 0000000000000000000000000000000000000000..b30f671617a67a09b01e8016f96b5de33e669e73 GIT binary patch literal 148 zcmV;F0BipriwFplNH<{u19W9`bTKzBba-?C3vmq&u~H~5Nh~Vi3IVg-{hX{646PKB zON&eLa}@$yLV@y`RjCSwK*4AQ69WYU2r^VKFj6ouRxmJ8FfdgxFjFuvS1_=MMK;C= zn=wWpV=Umt7-2O=!N3w`Qm8A~Jt?U Date: Tue, 7 Sep 2021 13:33:45 +0200 Subject: [PATCH 182/185] minor: T tracer: be more verbose for DLSCH DCI --- common/utils/T/T_messages.txt | 2 +- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index ca5690497d..cd66be73f5 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -16,7 +16,7 @@ ID = ENB_PHY_DL_TICK ID = ENB_PHY_DLSCH_UE_DCI DESC = eNodeB downlink UE specific DCI as sent by the PHY layer GROUP = ALL:PHY:GRAPHIC:ENB - FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS + FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS : int,ndi : int,rv : int,rbc : int,nb_rb : int,rb_alloc ID = ENB_PHY_DLSCH_UE_ACK DESC = eNodeB downlink UE ACK as seen by the PHY layer in process_HARQ_feedback GROUP = ALL:PHY:GRAPHIC:ENB diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 61af617d6e..1bbe9eb39a 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -1527,7 +1527,9 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB, if (dlsch0->active) T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(0), T_INT(frame), T_INT(subframe), T_INT(rel8->rnti), T_INT(rel8->dci_format), T_INT(rel8->harq_process), - T_INT(rel8->mcs_1), T_INT(dlsch0_harq->TBS)); + T_INT(rel8->mcs_1), T_INT(dlsch0_harq->TBS), T_INT(rel8->new_data_indicator_1), + T_INT(rel8->redundancy_version_1), T_INT(rel8->resource_block_coding), + T_INT(dlsch0_harq->nb_rb), T_INT(dlsch0_harq->rb_alloc[0])); #endif } From aa431f353f0cc239e60976f1e4c8e3999b4b2f1b Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 7 Sep 2021 15:13:10 +0200 Subject: [PATCH 183/185] new attempt to fix cdm both for sa and mimo --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 19 +++++++------------ .../NR_MAC_gNB/gNB_scheduler_primitives.c | 11 ++++++----- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 1736d68e65..ded1f3526d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -455,9 +455,7 @@ bool allocate_dl_retransmission(module_id_t module_id, int rbStart = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; - const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; - const uint8_t num_dmrs_cdm_grps_no_data = sched_ctrl->active_bwp ? (f ? 1 : (ps->nrOfSymbols == 2 ? 1 : 2)) : (ps->nrOfSymbols == 2 ? 1 : 2); - + const long f = sched_ctrl->active_bwp ? sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats : 0; int rbSize = 0; const int tda = sched_ctrl->active_bwp ? RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot] : 1; if (tda == retInfo->time_domain_allocation) { @@ -476,9 +474,8 @@ bool allocate_dl_retransmission(module_id_t module_id, } /* check whether we need to switch the TDA allocation since the last * (re-)transmission */ - if (ps->time_domain_allocation != tda || ps->numDmrsCdmGrpsNoData != num_dmrs_cdm_grps_no_data) - nr_set_pdsch_semi_static( - scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps); + if (ps->time_domain_allocation != tda) + nr_set_pdsch_semi_static(scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, f, ps); } else { /* the retransmission will use a different time domain allocation, check * that we have enough resources */ @@ -488,7 +485,7 @@ bool allocate_dl_retransmission(module_id_t module_id, rbSize++; NR_pdsch_semi_static_t temp_ps; temp_ps.nrOfLayers = 1; - nr_set_pdsch_semi_static(scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, &temp_ps); + nr_set_pdsch_semi_static(scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, f, &temp_ps); uint32_t new_tbs; uint16_t new_rbSize; bool success = nr_find_nb_rb(retInfo->Qm, @@ -683,11 +680,9 @@ void pf_dl(module_id_t module_id, const int tda = sched_ctrl->active_bwp ? RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot] : 1; NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; - const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; - const uint8_t num_dmrs_cdm_grps_no_data = sched_ctrl->active_bwp ? (f ? 1 : (ps->nrOfSymbols == 2 ? 1 : 2)) : (ps->nrOfSymbols == 2 ? 1 : 2); - if (ps->time_domain_allocation != tda || ps->numDmrsCdmGrpsNoData != num_dmrs_cdm_grps_no_data) - nr_set_pdsch_semi_static( - scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps); + const long f = sched_ctrl->active_bwp ? sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats : 0; + if (ps->time_domain_allocation != tda) + nr_set_pdsch_semi_static(scc, UE_info->CellGroup[UE_id], sched_ctrl->active_bwp, tda, f, ps); sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx); sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx); sched_pdsch->pucch_allocation = alloc; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 49c7af33f5..bbd4cb62f3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -299,7 +299,7 @@ void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc, const NR_CellGroupConfig_t *secondaryCellGroup, const NR_BWP_Downlink_t *bwp, int tda, - uint8_t num_dmrs_cdm_grps_no_data, + const long dci_format, NR_pdsch_semi_static_t *ps) { ps->time_domain_allocation = tda; @@ -325,12 +325,13 @@ void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc, } else ps->mcsTableIdx = 0; - set_dl_dmrs_ports(ps); + if(dci_format == 0) // format 1_0 + ps->numDmrsCdmGrpsNoData = (ps->nrOfSymbols == 2 ? 1 : 2); + else + set_dl_dmrs_ports(ps); ps->dmrsConfigType = bwp!=NULL ? (bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1) : 0; - // if no data in dmrs cdm group is 1 only even REs have no data - // if no data in dmrs cdm group is 2 both odd and even REs have no data - ps->N_PRB_DMRS = num_dmrs_cdm_grps_no_data * (ps->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); + ps->N_PRB_DMRS = ps->numDmrsCdmGrpsNoData * (ps->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); ps->dl_dmrs_symb_pos = fill_dmrs_mask(bwp ? bwp->bwp_Dedicated->pdsch_Config->choice.setup : NULL, scc->dmrs_TypeA_Position, ps->nrOfSymbols, ps->startSymbolIndex, mapping_type); ps->N_DMRS_SLOT = get_num_dmrs(ps->dl_dmrs_symb_pos); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 55ec901e28..9149c37538 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -280,7 +280,7 @@ void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc, const NR_CellGroupConfig_t *secondaryCellGroup, const NR_BWP_Downlink_t *bwp, int tda, - uint8_t num_dmrs_cdm_grps_no_data, + const long dci_format, NR_pdsch_semi_static_t *ps); void nr_set_pusch_semi_static(const NR_ServingCellConfigCommon_t *scc, From afdb5728ed1d6259aa1d8b97091b4a4b2ba2ebba Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 8 Sep 2021 14:21:28 +0200 Subject: [PATCH 184/185] fix for pointa computation in sib1 --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 30 +++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 7621a636f4..59c4ae09e5 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -419,14 +419,28 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, nrMultiBandInfo->freqBandIndicatorNR = configuration->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[i]; ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list,nrMultiBandInfo); } - int ref_scs; - if (configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) - ref_scs = 0; // 15 khz - if (configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) - ref_scs = 3; // 60 khz - uint32_t absolute_diff = (*configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); - sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA = - (absolute_diff/12) - (10<<(configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing - ref_scs)); + + int scs_scaling0 = 1<<(configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing); + int scs_scaling = scs_scaling0; + int scs_scaling2 = scs_scaling0; + if (configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) { + scs_scaling = scs_scaling0*3; + } + if (configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) { + scs_scaling = scs_scaling0>>2; + scs_scaling2 = scs_scaling0>>2; + } + uint32_t absolute_diff = (*configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - + configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); + + sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA = scs_scaling2 * (absolute_diff/(12*scs_scaling) - 10); + + LOG_I(NR_RRC,"SIB1 freq: absoluteFrequencySSB %ld, absoluteFrequencyPointA %ld\n", + *configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB, + configuration->scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); + LOG_I(NR_RRC,"SIB1 freq: absolute_diff %d, %d*(absolute_diff/(12*%d) - 10) %d\n", + absolute_diff,scs_scaling2,scs_scaling,(int)sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.offsetToPointA); + for(int i = 0; i< configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.count; i++) { ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list,configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[i]); } From 85378a707ef11c1c07469c3b721bb47a1976fef7 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 8 Sep 2021 16:27:58 +0200 Subject: [PATCH 185/185] fix(docker): NR-UE RHEL8 image is missing ip command Signed-off-by: Raphael Defosseux --- docker/Dockerfile.nrUE.rhel8.2 | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2 index f036c11483..56fc746ade 100644 --- a/docker/Dockerfile.nrUE.rhel8.2 +++ b/docker/Dockerfile.nrUE.rhel8.2 @@ -49,6 +49,7 @@ RUN yum update -y && \ nettle \ net-tools \ iputils \ + iproute \ atlas \ libXpm \ libX11 \