Skip to content
Snippets Groups Projects
Commit 1616ed77 authored by Thomas Schlichter's avatar Thomas Schlichter :flag_de:
Browse files

gNB: generalize rx_nr_prach_ru() and add support for mu==0

parent 8f632a7c
No related branches found
No related tags found
3 merge requests!1757Draft: Use pMAX value in configuration file, instead of hardcoded '23' in asn1_msg.c,!1572integration_2022_wk21b,!1490add support for 15 kHz SCS
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment