diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 4a2b22331b..ba860ece60 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1578,7 +1578,11 @@ void *ru_thread( void *param ) { // Do PRACH RU processing int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); if (prach_id>=0) { - rx_nr_prach_ru(ru,ru->prach_list[prach_id].fmt,proc->frame_rx,proc->tti_rx); + rx_nr_prach_ru(ru, + ru->prach_list[prach_id].fmt, + ru->prach_list[prach_id].numRA, + ru->prach_list[prach_id].prachStartSymbol, + proc->frame_rx,proc->tti_rx); free_nr_ru_prach_entry(ru,prach_id); } } diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index d010ce65d9..b2262949c1 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -387,7 +387,7 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, 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->nr_band = 78; - fp->threequarter_fs= 0; +// fp->threequarter_fs= 0; gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band); diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 9f9bb4694a..991084c485 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -120,9 +120,11 @@ void nr_fill_prach_ru(RU_t *ru, "illegal or no prach_id found!!! prach_id %d\n",prach_id); pthread_mutex_lock(&ru->prach_list_mutex); - ru->prach_list[prach_id].frame = SFN; - ru->prach_list[prach_id].slot = Slot; - ru->prach_list[prach_id].fmt = prach_pdu->prach_format; + ru->prach_list[prach_id].frame = SFN; + ru->prach_list[prach_id].slot = Slot; + ru->prach_list[prach_id].fmt = prach_pdu->prach_format; + ru->prach_list[prach_id].numRA = prach_pdu->num_ra; + ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol; pthread_mutex_unlock(&ru->prach_list_mutex); } @@ -139,7 +141,9 @@ void free_nr_ru_prach_entry(RU_t *ru, const char *prachfmt[]={"A1","A2","A3","B1","B2","B3","B4","C0","C2"}; void rx_nr_prach_ru(RU_t *ru, - int prach_fmt, + int prachFormat, + int numRA, + int prachStartSymbol, int frame, int slot) { @@ -151,7 +155,7 @@ void rx_nr_prach_ru(RU_t *ru, int16_t *prach[ru->nb_rx]; int prach_sequence_length = ru->config.prach_config.prach_sequence_length.value; - int msg1_frequencystart = ru->config.prach_config.num_prach_fd_occasions_list[0].k1.value; + int msg1_frequencystart = ru->config.prach_config.num_prach_fd_occasions_list[numRA].k1.value; rxsigF = ru->prach_rxsigF; @@ -167,9 +171,9 @@ void rx_nr_prach_ru(RU_t *ru, if (prach_sequence_length == 0) { LOG_D(PHY,"PRACH (ru %d) in %d.%d, format %d, msg1_frequencyStart %d\n", - ru->idx,frame,slot,prach_fmt,msg1_frequencystart); - AssertFatal(prach_fmt<4,"Illegal prach format %d for length 839\n",prach_fmt); - switch (prach_fmt) { + ru->idx,frame,slot,prachFormat,msg1_frequencystart); + AssertFatal(prachFormat<4,"Illegal prach format %d for length 839\n",prachFormat); + switch (prachFormat) { case 0: Ncp = 3168; break; @@ -189,11 +193,11 @@ void rx_nr_prach_ru(RU_t *ru, } } else { - LOG_D(PHY,"PRACH (ru %d) in %d.%d, format %s, msg1_frequencyStart %d\n", - ru->idx,frame,slot,prachfmt[prach_fmt],msg1_frequencystart); + LOG_D(PHY,"PRACH (ru %d) in %d.%d, format %s, msg1_frequencyStart %d,startSymbol %d\n", + ru->idx,frame,slot,prachfmt[prachFormat],msg1_frequencystart,prachStartSymbol); - switch (prach_fmt) { - AssertFatal(prach_fmt<4,"Illegal prach format %d for length 139 (combined formats not supported yet)\n",prach_fmt); + switch (prachFormat) { + AssertFatal(prachFormat<4,"Illegal prach format %d for length 139 (combined formats not supported yet)\n",prachFormat); case 0: //A1 Ncp = 288/(1<threequarter_fs==0) { //40 MHz @ 61.44 Ms/s //50 MHz @ 61.44 Ms/s - prach2 = prach[aa] + (Ncp<<2); + 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 (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=49152; dft49152(prach2,rxsigF[aa],1); } - if (prach_fmt == 1 || prach_fmt == 2) { + if (prachFormat == 1 || prachFormat == 2) { dft49152(prach2+98304,rxsigF[aa]+98304,1); reps++; } - if (prach_fmt == 2) { + if (prachFormat == 2) { dft49152(prach2+(98304*2),rxsigF[aa]+(98304*2),1); dft49152(prach2+(98304*3),rxsigF[aa]+(98304*3),1); reps+=2; } - if (prach_fmt == 3) { + if (prachFormat == 3) { dftlen=12288; for (int i=0;i<4;i++) dft12288(prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); reps=4; } - } + }// 839 sequence else { - dftlen=2048; - dft2048(prach2,rxsigF[aa],1); - if (prach_fmt != 7) { // !=C0 - dft2048(prach2+4096,rxsigF[aa]+4096,1); - reps++; - } - if (prach_fmt == 1 || prach_fmt == 2 || prach_fmt == 4 || prach_fmt == 5 || prach_fmt == 6 || prach_fmt == 8) { - dft2048(prach2+4096*2,rxsigF[aa]+4096*2,1); - dft2048(prach2+4096*3,rxsigF[aa]+4096*3,1); - reps+=2; - } - if (prach_fmt == 2 || prach_fmt == 5 || prach_fmt == 6) { - dft2048(prach2+4096*4,rxsigF[aa]+4096*4,1); - dft2048(prach2+4096*5,rxsigF[aa]+4096*5,1); - reps+=2; - } - if (prach_fmt == 6) { - for (int i=6;i<12;i++) dft2048(prach2+(4096*i),rxsigF[aa]+(4096*i),1); - reps+=6; + if ((mu==0 && + (prachStartSymbol == 0 || prachStartSymbol == 7)) || + (mu==1 && prachStartSymbol == 0)) prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) + + if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==1) { + dftlen=2048; + dft2048(prach2,rxsigF[aa],1); + if (prachFormat != 7) { // !=C0 + dft2048(prach2+4096,rxsigF[aa]+4096,1); + reps++; + } + if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { + dft2048(prach2+4096*2,rxsigF[aa]+4096*2,1); + dft2048(prach2+4096*3,rxsigF[aa]+4096*3,1); + reps+=2; + } + if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) { + dft2048(prach2+4096*4,rxsigF[aa]+4096*4,1); + dft2048(prach2+4096*5,rxsigF[aa]+4096*5,1); + reps+=2; + } + if (prachFormat == 6) { + for (int i=6;i<12;i++) dft2048(prach2+(4096*i),rxsigF[aa]+(4096*i),1); + reps+=6; + } } + else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); } - } else { + } else { // threequarter sampling // 40 MHz @ 46.08 Ms/s - prach2 = prach[aa] + (3*Ncp); + 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 (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2) { - dftlen=36864; + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { + dftlen=36864; dft36864(prach2,rxsigF[aa],1); reps++; } - if (prach_fmt == 1 || prach_fmt == 2) { + if (prachFormat == 1 || prachFormat == 2) { dft36864(prach2+73728,rxsigF[aa]+73728,1); reps++; } - if (prach_fmt == 2) { + if (prachFormat == 2) { dft36864(prach2+(73728*2),rxsigF[aa]+(73728*2),1); dft36864(prach2+(73728*3),rxsigF[aa]+(73728*3),1); reps+=2; } - if (prach_fmt == 3) { - dftlen=9216; + if (prachFormat == 3) { + dftlen=9216; for (int i=0;i<4;i++) dft9216(prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); reps=4; } } else { - dftlen=1536; - dft1536(prach2,rxsigF[aa],1); - if (prach_fmt != 7) { - dft1536(prach2+3072,rxsigF[aa]+3072,1); - reps++; - } - - if (prach_fmt == 1 || prach_fmt == 2 || prach_fmt == 4 || prach_fmt == 5 || prach_fmt == 6 || prach_fmt == 8) { - dft1536(prach2+3072*2,rxsigF[aa]+3072*2,1); - dft1536(prach2+3072*3,rxsigF[aa]+3072*3,1); - reps+=2; - } - if (prach_fmt == 2 || prach_fmt == 5 || prach_fmt == 6) { - dft1536(prach2+3072*4,rxsigF[aa]+3072*4,1); - dft1536(prach2+3072*5,rxsigF[aa]+3072*5,1); - reps+=2; - } - if (prach_fmt == 6) { - for (int i=6;i<12;i++) dft1536(prach2+(3072*i),rxsigF[aa]+(3072*i),1); - reps+=6; - } + if ((mu==0 && + (prachStartSymbol == 0 || prachStartSymbol == 7)) || + (mu==1 && prachStartSymbol == 0)) prach2+=48; // 24 samples @ 43.08 Ms/s in first symbol of each half subframe (15/30 kHz only) + if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==1) { + dftlen=1536; + dft1536(prach2,rxsigF[aa],1); + if (prachFormat != 7) { + dft1536(prach2+3072,rxsigF[aa]+3072,1); + reps++; + } + + if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { + dft1536(prach2+3072*2,rxsigF[aa]+3072*2,1); + dft1536(prach2+3072*3,rxsigF[aa]+3072*3,1); + reps+=2; + } + if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) { + dft1536(prach2+3072*4,rxsigF[aa]+3072*4,1); + dft1536(prach2+3072*5,rxsigF[aa]+3072*5,1); + reps+=2; + } + if (prachFormat == 6) { + for (int i=6;i<12;i++) dft1536(prach2+(3072*i),rxsigF[aa]+(3072*i),1); + reps+=6; + } + }// mu==1 + else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); } // short format } // 3/4 sampling } // <=50 MHz BW @@ -374,89 +397,109 @@ void rx_nr_prach_ru(RU_t *ru, //80,90,100 MHz @ 122.88 Ms/s if (prach_sequence_length == 0) { - if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=98304; dft98304(prach2,rxsigF[aa],1); } - if (prach_fmt == 1 || prach_fmt == 2) { + if (prachFormat == 1 || prachFormat == 2) { dft98304(prach2+196608,rxsigF[aa]+196608,1); reps++; } - if (prach_fmt == 2) { + if (prachFormat == 2) { dft98304(prach2+196608*2,rxsigF[aa]+196608*2,1); dft98304(prach2+(196608*3),rxsigF[aa]+(196608*3),1); reps+=2; } - if (prach_fmt == 3) { + if (prachFormat == 3) { dftlen=24576; for (int i=0;i<4;i++) dft24576(prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); reps=4; } } else { - dftlen=4096; - dft4096(prach2,rxsigF[aa],1); - if (prach_fmt != 7) { //!=C0 - dft4096(prach2+8192,rxsigF[aa]+8192,1); - reps++; - } - - if (prach_fmt == 1 || prach_fmt == 2 || prach_fmt == 4 || prach_fmt == 5 || prach_fmt == 6 || prach_fmt == 8) { - dft4096(prach2+8192*2,rxsigF[aa]+8192*2,1); - dft4096(prach2+8192*3,rxsigF[aa]+8192*3,1); - reps+=2; - } - if (prach_fmt == 2 || prach_fmt == 5 || prach_fmt == 6) { - dft4096(prach2+8192*4,rxsigF[aa]+8192*4,1); - dft4096(prach2+8192*5,rxsigF[aa]+8192*5,1); - reps+=2; - } - if (prach_fmt == 6) { - for (int i=6;i<12;i++) dft4096(prach2+(8192*i),rxsigF[aa]+(8192*i),1); - reps+=6; + if ((mu==0 && + (prachStartSymbol == 0 || prachStartSymbol == 7)) || + (mu==1 && prachStartSymbol == 0)) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + + if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==1) { + dftlen=4096; + dft4096(prach2,rxsigF[aa],1); + if (prachFormat != 7) { //!=C0 + dft4096(prach2+8192,rxsigF[aa]+8192,1); + reps++; + } + + if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { + dft4096(prach2+8192*2,rxsigF[aa]+8192*2,1); + dft4096(prach2+8192*3,rxsigF[aa]+8192*3,1); + reps+=2; + } + if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) { + dft4096(prach2+8192*4,rxsigF[aa]+8192*4,1); + dft4096(prach2+8192*5,rxsigF[aa]+8192*5,1); + reps+=2; + } + if (prachFormat == 6) { + for (int i=6;i<12;i++) dft4096(prach2+(8192*i),rxsigF[aa]+(8192*i),1); + reps+=6; + } } + else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); } } 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 (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2) { + if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=73728; dft73728(prach2,rxsigF[aa],1); reps++; } - if (prach_fmt == 1 || prach_fmt == 2) { + if (prachFormat == 1 || prachFormat == 2) { dft73728(prach2+(2*73728),rxsigF[aa]+(2*73728),1); reps++; } - if (prach_fmt == 3) { + if (prachFormat == 3) { dftlen=18432; for (int i=0;i<4;i++) dft18432(prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); reps=4; } } else { - dftlen=3072; - dft3072(prach2,rxsigF[aa],1); - if (prach_fmt != 7) { //!=C0 - dft3072(prach2+6144,rxsigF[aa]+6144,1); - reps++; - } - - if (prach_fmt == 1 || prach_fmt == 2 || prach_fmt == 4 || prach_fmt == 5 || prach_fmt == 6 || prach_fmt == 8) { - dft3072(prach2+6144*2,rxsigF[aa]+6144*2,1); - dft3072(prach2+6144*3,rxsigF[aa]+6144*3,1); - reps+=2; - } - if (prach_fmt == 2 || prach_fmt == 5 || prach_fmt == 6) { - dft3072(prach2+6144*4,rxsigF[aa]+6144*4,1); - dft3072(prach2+6144*5,rxsigF[aa]+6144*5,1); - reps+=2; - } - if (prach_fmt == 6) { - for (int i=6;i<12;i++) dft3072(prach2+(6144*i),rxsigF[aa]+(6144*i),1); - reps+=6; + if ((mu==0 && + (prachStartSymbol == 0 || prachStartSymbol == 7)) || + (mu==1 && prachStartSymbol == 0)) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + + if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==1) { + dftlen=3072; + dft3072(prach2,rxsigF[aa],1); + if (prachFormat != 7) { //!=C0 + dft3072(prach2+6144,rxsigF[aa]+6144,1); + reps++; + } + + if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { + dft3072(prach2+6144*2,rxsigF[aa]+6144*2,1); + dft3072(prach2+6144*3,rxsigF[aa]+6144*3,1); + reps+=2; + } + if (prachFormat == 2 || prachFormat == 5 || prachFormat == 6) { + dft3072(prach2+6144*4,rxsigF[aa]+6144*4,1); + dft3072(prach2+6144*5,rxsigF[aa]+6144*5,1); + reps+=2; + } + if (prachFormat == 6) { + for (int i=6;i<12;i++) dft3072(prach2+(6144*i),rxsigF[aa]+(6144*i),1); + reps+=6; + } } + else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); + else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); } } } @@ -724,7 +767,6 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, for (i=0; i*max_preamble_energy) { *max_preamble_energy = levdB; *max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport.h b/openair1/PHY/NR_TRANSPORT/nr_transport.h index 59e81fd0c5..157e309228 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport.h @@ -122,6 +122,8 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, void rx_nr_prach_ru(RU_t *ru, int prach_fmt, + int numRA, + int prachStartSymbol, int frame, int subframe); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index c144a37a06..34331a957d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -41,6 +41,8 @@ #include "T.h" +#define NR_PRACH_DEBUG 1 + extern uint16_t NCS_unrestricted_delta_f_RA_125[16]; extern uint16_t NCS_restricted_TypeA_delta_f_RA_125[15]; extern uint16_t NCS_restricted_TypeB_delta_f_RA_125[13]; @@ -111,7 +113,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) #else //normal case (simulation) prach_start = subframe*(fp->samples_per_slot<<1)-ue->N_TA_offset; - LOG_D(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id, + LOG_I(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id, prach_start, ue->rx_offset, ue->hw_timing_advance, @@ -222,7 +224,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) #ifdef NR_PRACH_DEBUG if (NCS>0) - LOG_D(PHY,"Generate PRACH for RootSeqIndex %d, Preamble Index %d, PRACH Format %x, prach_ConfigIndex %d, NCS %d (NCS_config %d, N_ZC/NCS %d): Preamble_offset %d, Preamble_shift %d\n", + LOG_I(PHY,"Generate PRACH for RootSeqIndex %d, Preamble Index %d, PRACH Format %x, prach_ConfigIndex %d, NCS %d (NCS_config %d, N_ZC/NCS %d): Preamble_offset %d, Preamble_shift %d\n", rootSequenceIndex,preamble_index,prach_fmt,prach_ConfigIndex,NCS,Ncs_config,N_ZC/NCS, preamble_offset,preamble_shift); @@ -251,7 +253,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) k*=K; k+=kbar; - LOG_D(PHY,"placing prach in position %d\n",k); + LOG_I(PHY,"placing prach in position %d\n",k); k*=2; Xu = (int16_t*)ue->X_u[preamble_offset-first_nonzero_root_idx]; @@ -427,6 +429,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) dftlen=12288; } else if (prach_fmt == 0xa1 || prach_fmt == 0xb1 || prach_fmt == 0xc0) { + Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); idft2048(prachF,prach2,1); dftlen=2048; @@ -440,6 +443,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) // here we have |Prefix | Prach2048 | Prach2048 (if ! 0xc0) | } else if (prach_fmt == 0xa2 || prach_fmt == 0xb2) { // 6x2048 + Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft2048(prachF,prach2,1); dftlen=2048; // here we have |empty | Prach2048 | @@ -452,6 +457,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (2048*4)+Ncp; } else if (prach_fmt == 0xa3 || prach_fmt == 0xb3) { // 6x2048 + Ncp+=32; prach2 = prach+(Ncp<<1); idft2048(prachF,prach2,1); dftlen=2048; @@ -467,6 +473,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (2048*6)+Ncp; } else if (prach_fmt == 0xb4) { // 12x2048 + Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft2048(prachF,prach2,1); dftlen=2048; // here we have |empty | Prach2048 | @@ -527,19 +535,23 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (9216*4)+Ncp; } else if (prach_fmt == 0xa1 || prach_fmt == 0xb1 || prach_fmt == 0xc0) { + Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft1536(prachF,prach2,1); dftlen=1536; // here we have |empty | Prach1536 | if (prach_fmt != 0xc0) { - memmove(prach2+(1536<<1),prach2,(1536<<2)); - prach_len = (1536*2)+Ncp; - } - else prach_len = (1536*1)+Ncp; + memmove(prach2+(1536<<1),prach2,(1536<<2)); + prach_len = (1536*2)+Ncp; + } + else prach_len = (1536*1)+Ncp; memmove(prach,prach+(1536<<1),(Ncp<<2)); // here we have |Prefix | Prach1536 | Prach1536 (if ! 0xc0) | } else if (prach_fmt == 0xa2 || prach_fmt == 0xb2) { // 6x1536 + Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft1536(prachF,prach2,1); dftlen=1536; // here we have |empty | Prach1536 | @@ -552,6 +564,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (1536*4)+Ncp; } else if (prach_fmt == 0xa3 || prach_fmt == 0xb3) { // 6x1536 + Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft1536(prachF,prach2,1); dftlen=1536; // here we have |empty | Prach1536 | @@ -566,6 +580,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (1536*6)+Ncp; } else if (prach_fmt == 0xb4) { // 12x1536 + Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft1536(prachF,prach2,1); dftlen=1536; // here we have |empty | Prach1536 | @@ -627,6 +643,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (24576*4)+Ncp; } else if (prach_fmt == 0xa1 || prach_fmt == 0xb1 || prach_fmt == 0xc0) { + Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft4096(prachF,prach2,1); dftlen=4096; // here we have |empty | Prach4096 | @@ -640,6 +658,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) } else if (prach_fmt == 0xa2 || prach_fmt == 0xb2) { // 4x4096 + Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft4096(prachF,prach2,1); dftlen=4096; // here we have |empty | Prach4096 | @@ -652,6 +672,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (4096*4)+Ncp; } else if (prach_fmt == 0xa3 || prach_fmt == 0xb3) { // 6x4096 + Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft4096(prachF,prach2,1); dftlen=4096; // here we have |empty | Prach4096 | @@ -666,6 +688,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (4096*6)+Ncp; } else if (prach_fmt == 0xb4) { // 12x4096 + Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft4096(prachF,prach2,1); dftlen=4096; // here we have |empty | Prach4096 | @@ -725,6 +749,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (18432*4)+Ncp; } else if (prach_fmt == 0xa1 || prach_fmt == 0xb1 || prach_fmt == 0xc0) { + Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft3072(prachF,prach2,1); dftlen=3072; // here we have |empty | Prach3072 | @@ -737,6 +763,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) // here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) | } else if (prach_fmt == 0xa3 || prach_fmt == 0xb3) { // 6x3072 + Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft3072(prachF,prach2,1); dftlen=3072; // here we have |empty | Prach3072 | @@ -751,6 +779,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (3072*6)+Ncp; } else if (prach_fmt == 0xa2 || prach_fmt == 0xb2) { // 4x3072 + Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft3072(prachF,prach2,1); dftlen=3072; // here we have |empty | Prach3072 | @@ -763,6 +793,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t subframe) prach_len = (3072*4)+Ncp; } else if (prach_fmt == 0xb4) { // 12x3072 + Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling + prach2 = prach+(Ncp<<1); idft3072(prachF,prach2,1); dftlen=3072; // here we have |empty | Prach3072 | diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 4cdb4bec76..128a40b02e 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -193,6 +193,8 @@ typedef struct { int frame; int slot; int fmt; + int numRA; + int prachStartSymbol; } RU_PRACH_list_t; #define NUMBER_OF_NR_RU_PRACH_MAX 8 diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 5d24700317..a5cd433437 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -212,9 +212,7 @@ void nr_dump_dlsch_SI(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id, #endif -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162}; -#endif int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){ @@ -4490,7 +4488,7 @@ uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue, void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, runmode_t runmode) { int frame_tx = proc->frame_tx, nr_tti_tx = proc->nr_tti_tx, prach_power, tx_amp; - uint16_t preamble_tx = 50, pathloss; + uint16_t /*preamble_tx = 50,*/ pathloss; uint8_t mod_id = ue->Mod_id; UE_MODE_t UE_mode = get_nrUE_mode(mod_id, ue->CC_id, gNB_id); NR_PRACH_RESOURCES_t * prach_resources = ue->prach_resources[gNB_id]; @@ -4499,7 +4497,7 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t ue->generate_nr_prach = 0; if (ue->mac_enabled == 0){ - prach_resources->ra_PreambleIndex = preamble_tx; + // prach_resources->ra_PreambleIndex = preamble_tx; prach_resources->ra_TDD_map_index = 0; prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = 10; prach_resources->ra_RNTI = 0x1234; @@ -4593,4 +4591,4 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t ue->generate_nr_prach = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_OUT); -} \ No newline at end of file +} diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index c9253aeedf..8aa5c3e81f 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -7,3 +7,342 @@ int32_t get_uldl_offset(int nr_bandP) { re 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); } int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(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 + */ + +/*! \file ra_procedures.c + * \brief Routines for UE MAC-layer Random Access procedures (TS 38.321, Release 15) + * \author R. Knopp, Navid Nikaein, Guido Casati + * \date 2019 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr navid.nikaein@eurecom.fr, guido.casati@iis.fraunhofer.de + * \note + * \warning + */ + +#include "mac.h" + +/* +#include "common/utils/LOG/vcd_signal_dumper.h" +#include "PHY_INTERFACE/phy_interface_extern.h" +#include "SCHED_UE/sched_UE.h" +#include "COMMON/mac_rrc_primitives.h" +#include "RRC/LTE/rrc_extern.h" +#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" +#include "common/utils/LOG/log.h" +#include "UTIL/OPT/opt.h" +#include "OCG.h" +#include "OCG_extern.h" +#include "PHY/LTE_ESTIMATION/lte_estimation.h"*/ + +/* Tools */ +#include "SIMULATION/TOOLS/sim.h" // for taus + +/* RRC */ +#include "NR_RACH-ConfigCommon.h" + +/* PHY */ +#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/defs_common.h" +#include "PHY/defs_nr_common.h" +#include "PHY/NR_UE_ESTIMATION/nr_estimation.h" + +/* MAC */ +#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" +#include "NR_MAC_COMMON/nr_mac.h" +#include "LAYER2/NR_MAC_UE/mac_proto.h" + +extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9]; +extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; + +//extern uint8_t nfapi_mode; + +// WIP +// This routine implements Section 5.1.2 (UE Random Access Resource Selection) +// and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321 +void nr_get_prach_resources(module_id_t mod_id, + int CC_id, + uint8_t gNB_id, + uint8_t t_id, + uint8_t first_Msg3, + NR_PRACH_RESOURCES_t *prach_resources, + NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon; + // NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo + + int messagePowerOffsetGroupB, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA, numberOfRA_Preambles, i, deltaPreamble_Msg3; + uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, msg1_FDM, prach_ConfigIndex, SFN_nbr, Msg3_size; + + // NR_RSRP_Range_t rsrp_ThresholdSSB; // todo + + /////////////////////////////////////////////////////////// + //////////* UE Random Access Resource Selection *////////// + /////////////////////////////////////////////////////////// + + // todo: + // - switch initialisation cases + // -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) + // --- SSB selection, set prach_resources->ra_PreambleIndex + // -- RA initiated by PDCCH: ra_preamble_index provided by PDCCH && ra_PreambleIndex != 0b000000 + // --- set PREAMBLE_INDEX to ra_preamble_index + // --- select the SSB signalled by PDCCH + // -- RA initiated for SI request: + // --- SSB selection, set prach_resources->ra_PreambleIndex + + // if (rach_ConfigDedicated) { // This is for network controlled Mobility + // // operation for contention-free RA resources when: + // // - available SSB with SS-RSRP above rsrp-ThresholdSSB: SSB selection + // // - availalbe CSI-RS with CSI-RSRP above rsrp-ThresholdCSI-RS: CSI-RS selection + // prach_resources->ra_PreambleIndex = rach_ConfigDedicated->ra_PreambleIndex; + // return; + // } + + //////////* Contention-based RA preamble selection *////////// + // todo: + // - selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB + // - todo determine next available PRACH occasion + + // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB; + + AssertFatal(mac->nr_rach_ConfigCommon != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id); + + nr_rach_ConfigCommon = mac->nr_rach_ConfigCommon; + + Msg3_size = mac->RA_Msg3_size; + numberOfRA_Preambles = *nr_rach_ConfigCommon->totalNumberOfRA_Preambles; + + if (!nr_rach_ConfigCommon->groupBconfigured) { + noGroupB = 1; + } else { + // RA preambles group B is configured + // - Defining the number of RA preambles in RA Preamble Group A for each SSB */ + sizeOfRA_PreamblesGroupA = nr_rach_ConfigCommon->groupBconfigured->numberOfRA_PreamblesGroupA; + switch (nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA){ + /* - Threshold to determine the groups of RA preambles */ + case 0: + messageSizeGroupA = 56; + break; + case 1: + messageSizeGroupA = 144; + break; + case 2: + messageSizeGroupA = 208; + break; + case 3: + messageSizeGroupA = 256; + break; + case 4: + messageSizeGroupA = 282; + break; + case 5: + messageSizeGroupA = 480; + break; + case 6: + messageSizeGroupA = 640; + break; + case 7: + messageSizeGroupA = 800; + break; + case 8: + messageSizeGroupA = 1000; + break; + case 9: + messageSizeGroupA = 72; + break; + default: + AssertFatal(1 == 0,"Unknown ra_Msg3SizeGroupA %lu\n", nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA); + /* todo cases 10 -15*/ + } + + /* Power offset for preamble selection in dB */ + messagePowerOffsetGroupB = -9999; + switch (nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB){ + case 0: + messagePowerOffsetGroupB = -9999; + break; + case 1: + messagePowerOffsetGroupB = 0; + break; + case 2: + messagePowerOffsetGroupB = 5; + break; + case 3: + messagePowerOffsetGroupB = 8; + break; + case 4: + messagePowerOffsetGroupB = 10; + break; + case 5: + messagePowerOffsetGroupB = 12; + break; + case 6: + messagePowerOffsetGroupB = 15; + break; + case 7: + messagePowerOffsetGroupB = 18; + break; + default: + AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB); + } + + // todo Msg3-DeltaPreamble should be provided from higher layers, otherwise is 0 + mac->deltaPreamble_Msg3 = 0; + deltaPreamble_Msg3 = mac->deltaPreamble_Msg3; + } + + PLThreshold = prach_resources->RA_PCMAX - nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; + + /* Msg3 has not been transmitted yet */ + if (first_Msg3 == 1) { + if (noGroupB == 1) { + // use Group A preamble + prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; + mac->RA_usedGroupA = 1; + } else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) { + // Group B is configured and RA preamble Group A is used + // - todo add condition on CCCH_sdu_size for initiation by CCCH + prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; + mac->RA_usedGroupA = 1; + } else { + // Group B preamble is configured and used + // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A + // the remaining belong to RA Preambles Group B + prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); + mac->RA_usedGroupA = 0; + } + } else { // Msg3 is being retransmitted + if (mac->RA_usedGroupA == 1 && noGroupB == 1) { + prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles; + } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){ + prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA; + } else { + prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA); + } + } + + // todo determine next available PRACH occasion + // - if RA initiated for SI request and ra_AssociationPeriodIndex and si-RequestPeriod are configured + // - else if SSB is selected above + // - else if CSI-RS is selected above + + ///////////////////////////////////////////////////////////////////////////// + //////////* Random Access Preamble Transmission (5.1.3 TS 38.321) *////////// + ///////////////////////////////////////////////////////////////////////////// + // todo: + // - condition on notification of suspending power ramping counter from lower layer (5.1.3 TS 38.321) + // - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission + // - Extend RA_rnti computation (e.g. f_id selection, ul_carrier_id are hardcoded) + + if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER > 1) + mac->RA_PREAMBLE_TRANSMISSION_COUNTER++; + + prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id); + + // RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted) + // 1) this does not apply to contention-free RA Preamble for beam failure recovery request + // 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario) + + switch (nr_rach_ConfigCommon->rach_ConfigGeneric.msg1_FDM){ // todo this is not used + case 0: + msg1_FDM = 1; + break; + case 1: + msg1_FDM = 2; + break; + case 2: + msg1_FDM = 4; + break; + case 3: + msg1_FDM = 8; + break; + default: + AssertFatal(1 == 0,"Unknown msg1_FDM %lu\n", nr_rach_ConfigCommon->rach_ConfigGeneric.msg1_FDM); + } + + prach_ConfigIndex = nr_rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; + + // ra_RNTI computation + // - todo: this is for TDD FR1 only + // - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier + // - f_id: index of the PRACH occasion in the frequency domain + // - s_id is starting symbol of the PRACH occasion [0...14] + // - t_id is the first slot of the PRACH occasion in a system frame [0...80] + + ul_carrier_id = 0; // NUL + f_id = nr_rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart; + SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4]; + s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5]; + + // Pick the first slot of the PRACH occasion in a system frame + for (i = 0; i < 10; i++){ + if (((SFN_nbr & (1 << i)) >> i) == 1){ + t_id = 2*i; + break; + } + } + prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; + mac->ra_rnti = prach_resources->ra_RNTI; + + LOG_D(MAC, "Computed ra_RNTI is %d", prach_resources->ra_RNTI); +} + +// TbD: RA_attempt_number not used +void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){ + AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + mac->ra_state = WAIT_RAR; + // Start contention resolution timer + mac->RA_attempt_number++; +} + +void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, 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); + // start contention resolution timer + mac->RA_contention_resolution_cnt = 0; + mac->RA_contention_resolution_timer_active = 1; +} + +///////////////////////////////////////////////////////////////////////// +///////* Random Access Preamble Initialization (5.1.1 TS 38.321) */////// +///////////////////////////////////////////////////////////////////////// +/// Handling inizialization by PDCCH order, MAC entity or RRC (TS 38.300) +/// Only one RA procedure is ongoing at any point in time in a MAC entity +/// the RA procedure on a SCell shall only be initiated by PDCCH order + +// WIP +// todo TS 38.321: +// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX +// - BWP operation (subclause 5.15 TS 38.321) +// - handle initialization by beam failure recovery +// - handle initialization by handover +// - handle transmission on DCCH using PRACH (during handover, or sending SR for example) +// - take into account MAC CEs in size_sdu (currently hardcoded size to 1 MAC subPDU and 1 padding subheader) +// - fix rrc data req logic +// - retrieve TBS +// - add mac_rrc_nr_data_req_ue, etc ... +// - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) + + diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index 78596cc792..1b2a07514a 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -55,4 +55,15 @@ signed char quantize(double D, double x, unsigned char B) { return ((char) qxd); } +int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe) { + AssertFatal(1==0,"Shouldn't be here ...\n"); + 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); } + + + #endif diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 33ee14424c..64df0bc1f2 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -42,11 +42,15 @@ #include "PHY/MODULATION/modulation_UE.h" #include "PHY/INIT/phy_init.h" #include "PHY/NR_TRANSPORT/nr_transport.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto_common.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" +#include "nr_unitary_defs.h" #include "OCG_vars.h" #include + + PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; @@ -59,27 +63,33 @@ extern uint16_t prach_root_sequence_map0_3[838]; void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe); uint16_t NB_UE_INST=1; -volatile int oai_exit=0; - -void exit_function(const char* file, const char* function, const int line,const char *s) { - const char * msg= s==NULL ? "no comment": s; - printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg); - exit(-1); -} -int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe) { - AssertFatal(1==0,"Shouldn't be here ...\n"); - return 0; -} - -int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {return(0);} openair0_config_t openair0_cfg[MAX_CARDS]; uint8_t nfapi_mode=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); } +void nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, + module_id_t mod_id, + int CC_id, + UE_MODE_t UE_mode, + frame_t frame, + uint8_t gNB_id, + int nr_tti_tx) { return;} + +void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id) { return;} + +uint16_t nr_ue_process_rar(module_id_t mod_id, + int CC_id, + frame_t frameP, + uint8_t * dlsch_buffer, + rnti_t * t_crnti, + uint8_t preamble_index, + uint8_t * selected_rar_buffer) { return 0;} + +int is_nr_prach_subframe(NR_DL_FRAME_PARMS *fp,uint32_t frame,uint8_t slot) { return(1);} + +int get_nr_prach_fmt(int prachConfigIndex,int frame_type,int fr) { return(0xa2); } int main(int argc, char **argv) { @@ -203,7 +213,7 @@ int main(int argc, char **argv) break; default: - msg("Unsupported channel model!\n"); + printf("Unsupported channel model!\n"); exit(-1); } @@ -219,13 +229,13 @@ int main(int argc, char **argv) case 's': snr0 = atof(optarg); - msg("Setting SNR0 to %f\n",snr0); + printf("Setting SNR0 to %f\n",snr0); break; case 'S': snr1 = atof(optarg); snr1set=1; - msg("Setting SNR1 to %f\n",snr1); + printf("Setting SNR1 to %f\n",snr1); break; case 'p': @@ -268,7 +278,7 @@ int main(int argc, char **argv) if ((transmission_mode!=1) && (transmission_mode!=2) && (transmission_mode!=6)) { - msg("Unsupported transmission mode %d\n",transmission_mode); + printf("Unsupported transmission mode %d\n",transmission_mode); exit(-1); } @@ -278,7 +288,7 @@ int main(int argc, char **argv) n_tx=atoi(optarg); if ((n_tx==0) || (n_tx>2)) { - msg("Unsupported number of tx antennas %d\n",n_tx); + printf("Unsupported number of tx antennas %d\n",n_tx); exit(-1); } @@ -288,7 +298,7 @@ int main(int argc, char **argv) n_rx=atoi(optarg); if ((n_rx==0) || (n_rx>2)) { - msg("Unsupported number of rx antennas %d\n",n_rx); + printf("Unsupported number of rx antennas %d\n",n_rx); exit(-1); } @@ -400,10 +410,24 @@ int main(int argc, char **argv) ru->nb_tx = n_tx; ru->nb_rx = n_rx; + gNB->gNB_config.carrier_config.num_tx_ant.value=1; + gNB->gNB_config.carrier_config.num_rx_ant.value=1; + gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(gNB->gNB_config.prach_config.num_prach_fd_occasions.value*sizeof(nfapi_nr_num_prach_fd_occasions_t)); + gNB->gNB_config.prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index.value = 1; + gNB->gNB_config.prach_config.num_prach_fd_occasions_list[0].num_root_sequences.value = 16; + gNB->gNB_config.prach_config.prach_sequence_length.value = 1; + gNB->gNB_config.prach_config.num_prach_fd_occasions_list[0].k1.value = 0; + gNB->gNB_config.prach_config.restricted_set_config.value = 0; + gNB->gNB_config.tdd_table.tdd_period.value = 6; + + memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); + RC.nb_nr_L1_inst=1; phy_init_nr_gNB(gNB,0,0); nr_phy_init_RU(ru); - set_tdd_config_nr(&gNB->gNB_config, 5000, + + + set_tdd_config_nr(&gNB->gNB_config, 1, 7, 6, 2, 4); @@ -481,21 +505,9 @@ int main(int argc, char **argv) gNB->common_vars.rxdata = ru->common.rxdata; - compute_nr_prach_seq(gNB->frame_parms.prach_config_common.rootSequenceIndex, - gNB->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - gNB->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - gNB->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag, - gNB->frame_parms.frame_type, - gNB->frame_parms.freq_range, - gNB->X_u); + compute_nr_prach_seq(&gNB->gNB_config,0,gNB->X_u); - compute_nr_prach_seq(UE->frame_parms.prach_config_common.rootSequenceIndex, - UE->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - UE->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - UE->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag, - UE->frame_parms.frame_type, - UE->frame_parms.freq_range, - UE->X_u); + compute_nr_prach_seq(&gNB->gNB_config,0,UE->X_u); @@ -517,6 +529,7 @@ int main(int argc, char **argv) subframe); */ //commented for testing purpose UE_nr_rxtx_proc_t proc={0}; + proc.frame_tx=0;proc.nr_tti_tx=subframe; nr_ue_prach_procedures(UE,&proc,0,0); /* tx_lev_dB not used later, no need to set */ @@ -526,7 +539,7 @@ int main(int argc, char **argv) //LOG_M("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); // multipath channel - dump_nr_prach_config(&gNB->frame_parms,subframe); + // dump_nr_prach_config(&gNB->frame_parms,subframe); for (i=0; isamples_per_slot<<1; i++) { for (aa=0; aa<1; aa++) { @@ -589,18 +602,26 @@ int main(int argc, char **argv) } uint16_t preamble_rx; rx_nr_prach_ru(ru, + 1, 0, - subframe); + 0, + 0, + subframe<<1); gNB->prach_vars.rxsigF = ru->prach_rxsigF; + + nfapi_nr_prach_pdu_t prach_pdu; + prach_pdu.num_cs = 34; + prach_pdu.prach_format = 1; // A2 + rx_nr_prach(gNB, + &prach_pdu, 0, - subframe, + subframe<<1, &preamble_rx, &preamble_energy, &preamble_delay); - printf("preamble_rx %d\n", preamble_rx); - if (preamble_rx!=preamble_tx) + if (preamble_rx!=preamble_tx) prach_errors++; else { delay_avg += (double)preamble_delay; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index eaaa47df25..f928aeb572 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -600,4 +600,4 @@ void nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, } prach_resources = NULL; return; -} \ No newline at end of file +} diff --git a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c index f0ba789266..20864ccc97 100644 --- a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c +++ b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c @@ -134,4 +134,4 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, memcpy((void *) (selected_rar_buffer + 1), (void *) rar, sizeof(NR_MAC_RAR)); return ta_command; -} \ No newline at end of file +}