diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index ed8eba4940303ed053ebc4b91d3898394364eac4..dce98b70f0e0ffe1cf6358e6b99c94a760d0688b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -200,89 +200,167 @@ void rx_nr_prach_ru(RU_t *ru, prach[aa] = (int16_t*)&ru->common.rxdata[aa][fp->get_samples_slot_timestamp(slot2,fp,0)+sample_offset_slot-ru->N_TA_offset]; } - idft_size_idx_t dftsize; - int dftlen=0; + int reps; + int Ncp; + int dftlen; int mu = fp->numerology_index; - int Ncp = 0; - int16_t *prach2; if (prach_sequence_length == 0) { LOG_D(PHY,"PRACH (ru %d) in %d.%d, format %d, msg1_frequencyStart %d\n", ru->idx,frame,slot2,prachFormat,msg1_frequencystart); - AssertFatal(prachFormat<4,"Illegal prach format %d for length 839\n",prachFormat); switch (prachFormat) { case 0: + reps = 1; Ncp = 3168; + dftlen = 24576; break; - + case 1: + reps = 2; Ncp = 21024; + dftlen = 24576; break; - + case 2: + reps = 4; Ncp = 4688; + dftlen = 24576; break; - + case 3: + reps = 4; Ncp = 3168; + dftlen = 6144; + break; + + default: + AssertFatal(1==0, "Illegal prach format %d for length 839\n", prachFormat); break; - } } else { 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 (prachFormat) { case 4: //A1 - Ncp = 288/(1<<mu); + reps = 2; + Ncp = 288 >> mu; break; - + case 5: //A2 - Ncp = 576/(1<<mu); + reps = 4; + Ncp = 576 >> mu; break; - + case 6: //A3 - Ncp = 864/(1<<mu); + reps = 6; + Ncp = 864 >> mu; break; - + case 7: //B1 - Ncp = 216/(1<<mu); - break; - + reps = 2; + Ncp = 216 >> mu; + break; + /* // B2 and B3 do not exist in FAPI case 4: //B2 - Ncp = 360/(1<<mu); + reps = 4; + Ncp = 360 >> mu; break; - + case 5: //B3 - Ncp = 504/(1<<mu); + reps = 6; + Ncp = 504 >> mu; break; */ + case 8: //B4 - Ncp = 936/(1<<mu); + reps = 12; + Ncp = 936 >> mu; break; - + case 9: //C0 - Ncp = 1240/(1<<mu); + reps = 1; + Ncp = 1240 >> mu; break; - + case 10: //C2 - Ncp = 2048/(1<<mu); + reps = 4; + Ncp = 2048 >> mu; break; - + default: AssertFatal(1==0,"unknown prach format %x\n",prachFormat); break; } + dftlen = 2048 >> mu; + } + + //actually what we should be checking here is how often the current prach crosses a 0.5ms boundary. I am not quite sure for which paramter set this would be the case, so I will ignore it for now and just check if the prach starts on a 0.5ms boundary + if(fp->numerology_index == 0) { + if (prachStartSymbol == 0 || prachStartSymbol == 7) + Ncp += 16; + } + else { + if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + Ncp += 16; } + + switch(fp->samples_per_subframe) { + case 7680: + // 5 MHz @ 7.68 Ms/s + Ncp >>= 2; + dftlen >>= 2; + break; + + case 15360: + // 10, 15 MHz @ 15.36 Ms/s + Ncp >>= 1; + dftlen >>= 1; + break; + + case 30720: + // 20, 25, 30 MHz @ 30.72 Ms/s + Ncp = Ncp; + dftlen = dftlen; + break; + + case 46080: + // 40 MHz @ 46.08 Ms/s + Ncp = (Ncp*3)/2; + dftlen = (dftlen*3)/2; + break; + + case 61440: + // 40, 50, 60 MHz @ 61.44 Ms/s + Ncp <<= 1; + dftlen <<= 1; + break; + + case 92160: + // 50, 60, 70, 80, 90 MHz @ 92.16 Ms/s + Ncp *= 3; + dftlen *= 3; + break; + + case 122880: + // 70, 80, 90, 100 MHz @ 122.88 Ms/s + Ncp <<= 2; + dftlen <<= 2; + break; + + default: + AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); + } + + const idft_size_idx_t dftsize = get_dft(dftlen); + // Do forward transform if (LOG_DEBUGFLAG(PRACH)) { - LOG_D(PHY,"rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d\n",ru->nb_rx, Ncp); + LOG_D(PHY, "rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d dftlen:%d\n", ru->nb_rx, Ncp, dftlen); } - // Note: Assumes PUSCH SCS @ 30 kHz, take values for formats 0-2 and adjust for others below int kbar = 1; @@ -306,357 +384,13 @@ void rx_nr_prach_ru(RU_t *ru, k*=K; k+=kbar; - int reps=1; - for (int aa=0; aa<ru->nb_rx; aa++) { AssertFatal(prach[aa]!=NULL,"prach[%d] is null\n",aa); // do DFT - if (mu==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; - } - } - break; - - 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) - - 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; - } - } - break; - - 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=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); - } - if (prach_sequence_length == 0) { - AssertFatal(1==0,"long prach not supported for numerology %d\n",mu); - } - if (fp->N_RB_UL == 32) { - prach2 = prach[aa] + (Ncp<<2); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 for 61.44Msps - if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) - prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe - dftlen=512; - dftsize = DFT_512; - } - else if (fp->N_RB_UL == 66) { - prach2 = prach[aa] + (Ncp<<3); // Ncp is for 30.72 Ms/s, so multiply by 4 for I/Q, and 2 for 122.88Msps - if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) - prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe - dftlen=1024; - dftsize = DFT_1024; - } - else { - AssertFatal(1==0,"N_RB_UL %d not support for numerology %d\n",fp->N_RB_UL,mu); - } - - dft(dftsize,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(dftsize,prach2+dftlen*2,rxsigF[aa]+dftlen*2,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(dftsize,prach2+dftlen*4,rxsigF[aa]+dftlen*4,1); - dft(dftsize,prach2+dftlen*6,rxsigF[aa]+dftlen*6,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(dftsize,prach2+dftlen*8,rxsigF[aa]+dftlen*8,1); - dft(dftsize,prach2+dftlen*10,rxsigF[aa]+dftlen*10,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) - dft(dftsize,prach2+(dftlen*2*i),rxsigF[aa]+(dftlen*2*i),1); - reps+=6; - } - } - else { - AssertFatal(1==0,"Numerology not supported\n"); - } + int16_t *prach2 = prach[aa] + (2*Ncp); // times 2 for complex samples + for (int i = 0; i < reps; i++) + dft(dftsize, prach2 + 2*dftlen*i, rxsigF[aa] + 2*dftlen*i, 1); //LOG_M("ru_rxsigF_tmp.m","rxsFtmp", rxsigF[aa], dftlen*2*reps, 1, 1);