nr_ul_channel_estimation.c 28.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * 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.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.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 <string.h>

#include "nr_ul_estimation.h"
26
#include "PHY/sse_intrin.h"
27
#include "PHY/NR_REFSIG/nr_refsig.h"
28
#include "PHY/NR_REFSIG/dmrs_nr.h"
29 30
#include "PHY/NR_REFSIG/ptrs_nr.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
31 32
#include "PHY/NR_UE_ESTIMATION/filt16a_32.h"

dir's avatar
dir committed
33 34 35
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"


Francesco Mani's avatar
Francesco Mani committed
36 37
//#define DEBUG_CH
//#define DEBUG_PUSCH
38

39 40
#define dBc(x,y) (dB_fixed(((int32_t)(x))*(x) + ((int32_t)(y))*(y)))

41
int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
42 43 44
                                unsigned char Ns,
                                unsigned short p,
                                unsigned char symbol,
45
                                int ul_id,
46
                                unsigned short bwp_start_subcarrier,
47 48
                                nfapi_nr_pusch_pdu_t *pusch_pdu) {

49
  int pilot[3280] __attribute__((aligned(16)));
50 51
  unsigned char aarx;
  unsigned short k;
52 53
  unsigned int pilot_cnt,re_cnt;
  int16_t ch[2],ch_r[2],ch_l[2],*pil,*rxF,*ul_ch;
54
  int16_t *fl,*fm,*fr,*fml,*fmr,*fmm,*fdcl,*fdcr,*fdclh,*fdcrh;
55 56
  int ch_offset,symbol_offset ;
  int32_t **ul_ch_estimates_time =  gNB->pusch_vars[ul_id]->ul_ch_estimates_time;
57
  __m128i *ul_ch_128;
58 59 60 61 62 63 64 65 66

#ifdef DEBUG_CH
  FILE *debug_ch_est;
  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;
67
  int **ul_ch_estimates  = gNB->pusch_vars[ul_id]->ul_ch_estimates;
68
  int **rxdataF = gNB->common_vars.rxdataF;
Eurecom's avatar
Eurecom committed
69
  int soffset = (Ns&3)*gNB->frame_parms.symbols_per_slot*gNB->frame_parms.ofdm_symbol_size;
70 71 72 73 74 75 76 77
  nushift = (p>>1)&1;
  gNB->frame_parms.nushift = nushift;

  ch_offset     = gNB->frame_parms.ofdm_symbol_size*symbol;

  symbol_offset = gNB->frame_parms.ofdm_symbol_size*symbol;

  k = bwp_start_subcarrier;
78
  int re_offset;
79

80 81
  uint16_t nb_rb_pusch = pusch_pdu->rb_size;

82
  LOG_D(PHY, "In %s: ch_offset %d, soffset %d, symbol_offset %d OFDM size %d, Ns = %d, k = %d symbol %d\n",
cig's avatar
cig committed
83
        __FUNCTION__,
Eurecom's avatar
Eurecom committed
84
        ch_offset, soffset,
cig's avatar
cig committed
85 86 87 88 89 90
        symbol_offset,
        gNB->frame_parms.ofdm_symbol_size,
        Ns,
        k,
        symbol);

91 92 93 94 95 96 97 98
  switch (nushift) {
   case 0:
         fl = filt8_l0;
         fm = filt8_m0;
         fr = filt8_r0;
         fmm = filt8_mm0;
         fml = filt8_m0;
         fmr = filt8_mr0;
99 100 101 102
         fdcl = filt8_dcl0;
         fdcr = filt8_dcr0;
         fdclh = filt8_dcl0_h;
         fdcrh = filt8_dcr0_h;
103 104 105 106 107 108 109 110 111
         break;

   case 1:
         fl = filt8_l1;
         fm = filt8_m1;
         fr = filt8_r1;
         fmm = filt8_mm1;
         fml = filt8_ml1;
         fmr = filt8_m1;
112 113 114 115
         fdcl = filt8_dcl1;
         fdcr = filt8_dcr1;
         fdclh = filt8_dcl1_h;
         fdcrh = filt8_dcr1_h;
116 117 118
         break;

   default:
119 120 121 122 123
#ifdef DEBUG_CH
      if (debug_ch_est)
        fclose(debug_ch_est);

#endif
124 125 126 127 128 129
     return(-1);
     break;
   }

  //------------------generate DMRS------------------//

130
  // transform precoding = 1 means disabled
131 132 133
  if (pusch_pdu->transform_precoding == 1) {
    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->bwp_start + pusch_pdu->rb_start)*NR_NB_SC_PER_RB, pusch_pdu->dmrs_config_type);
cig's avatar
cig committed
134
  }
dir's avatar
dir committed
135 136 137 138 139 140 141 142 143 144
  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
    uint16_t index = get_index_for_dmrs_lowpapr_seq(nb_rb_pusch * (NR_NB_SC_PER_RB/2));
    uint8_t u = pusch_pdu->dfts_ofdm.low_papr_group_number; 
    uint8_t v = pusch_pdu->dfts_ofdm.low_papr_sequence_number;
    int16_t *dmrs_seq = gNB_dmrs_lowpaprtype1_sequence[u][v][index];

    AssertFatal(index >= 0, "Num RBs not configured according to 3GPP 38.211 section 6.3.1.4. For PUSCH with transform precoding, num RBs cannot be multiple of any other primenumber other than 2,3,5\n");
    AssertFatal(dmrs_seq != NULL, "DMRS low PAPR seq not found, check if DMRS sequences are generated");
145

dir's avatar
dir committed
146 147 148 149 150 151 152 153 154 155
    LOG_D(PHY,"Transform Precoding params. u: %d, v: %d, index for dmrsseq: %d\n", u, v, index);
    
    nr_pusch_lowpaprtype1_dmrs_rx(gNB, Ns, dmrs_seq, &pilot[0], 1000, 0, nb_rb_pusch, 0, pusch_pdu->dmrs_config_type);    

    #ifdef DEBUG_PUSCH
      printf ("NR_UL_CHANNEL_EST: index %d, u %d,v %d\n", index, u, v);
      LOG_M("gNb_DMRS_SEQ.m","gNb_DMRS_SEQ", dmrs_seq,6*nb_rb_pusch,1,1);
    #endif

  }
156
  //------------------------------------------------//
dir's avatar
dir committed
157 158


159
#ifdef DEBUG_PUSCH
cig's avatar
cig committed
160 161 162 163 164 165
  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)]);
  }
166
#endif
cig's avatar
cig committed
167

168 169
  for (aarx=0; aarx<gNB->frame_parms.nb_antennas_rx; aarx++) {

Saankhya's avatar
Saankhya committed
170 171
    re_offset = k;   /* Initializing the Resource element offset for each Rx antenna */

172
    pil   = (int16_t *)&pilot[0];
Eurecom's avatar
Eurecom committed
173
    rxF   = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+k+nushift)];
174
    ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
175
    re_offset = k;
176

177
    memset(ul_ch,0,4*(gNB->frame_parms.ofdm_symbol_size));
178 179

#ifdef DEBUG_PUSCH
cig's avatar
cig committed
180 181 182 183 184
    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);
185
#endif
186
    //if ((gNB->frame_parms.N_RB_UL&1)==0) {
187

188
    if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1){
189

190 191 192 193 194
      // 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_PUSCH
cig's avatar
cig committed
195 196 197 198 199 200 201 202 203 204 205 206
      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]));
207
#endif
208

209 210 211 212 213
      multadd_real_vector_complex_scalar(fl,
                                         ch,
                                         ul_ch,
                                         8);
      pil+=2;
214
      re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
215
      rxF   = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)];
216 217 218 219 220 221 222
      //for (int i= 0; i<8; i++)
      //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_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_PUSCH
cig's avatar
cig committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
      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]));
238
#endif
cig's avatar
cig committed
239

240 241 242 243 244
      multadd_real_vector_complex_scalar(fml,
                                         ch,
                                         ul_ch,
                                         8);
      pil+=2;
245
      re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
246
      rxF   = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)];
247 248 249 250 251 252
      //printf("ul_ch addr %p\n",ul_ch);
      
      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_PUSCH
cig's avatar
cig committed
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
      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]));
268
#endif
cig's avatar
cig committed
269

270 271 272 273 274 275 276 277 278
      multadd_real_vector_complex_scalar(fmm,
                                         ch,
                                         ul_ch,
                                         8);
                                         
      //for (int i= 0; i<16; i++)
      //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i));
      
      pil+=2;
279
      re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
280
      rxF   = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)];
281 282 283 284 285 286
      ul_ch+=8;

      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);
287 288

  #ifdef DEBUG_PUSCH
289 290
        printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
	printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt,rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
291 292
  #endif
        multadd_real_vector_complex_scalar(fml,
293 294 295 296
                                           ch,
                                           ul_ch,
                                           8);
        pil+=2;
297
        re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
298
        rxF   = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)];
299 300
        //printf("ul_ch addr %p\n",ul_ch);

301 302
        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);
303 304

  #ifdef DEBUG_PUSCH
305 306
        printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
	printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+1,rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
307
  #endif
308 309 310 311
        multadd_real_vector_complex_scalar(fmm,
                                           ch,
                                           ul_ch,
                                           8);
312 313 314 315

        //for (int i= 0; i<16; i++)
        //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i));

316
        pil+=2;
317
        re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
318
        rxF   = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)];
319 320 321 322 323
        ul_ch+=8;

      }
      
      // Treat first 2 pilots specially (right edge)
324
      ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
325 326
      ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
#ifdef DEBUG_PUSCH
327 328
      printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
      printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt,rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
329 330 331 332 333 334 335 336 337 338
#endif
      multadd_real_vector_complex_scalar(fm,
                                         ch,
                                         ul_ch,
                                         8);
                                         
      //for (int i= 0; i<8; i++)
      //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i));

      pil+=2;
339
      re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
340
      rxF   = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)];
341 342 343 344 345
             
      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_PUSCH
      printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
346 347
      printf("pilot %u : rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
      printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+1,rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
348 349 350 351 352 353 354
#endif
      multadd_real_vector_complex_scalar(fmr,
                                         ch,
                                         ul_ch,
                                         8);
                                         
      pil+=2;
355
      re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
356
      rxF   = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)];
357 358 359 360 361
      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);
#ifdef DEBUG_PUSCH
362 363
      printf("pilot %u: rxF - > (%d,%d) (%d) ch -> (%d,%d) (%d), pil -> (%d,%d) \n",pilot_cnt+2,rxF[0],rxF[1],dBc(rxF[0],rxF[1]),ch[0],ch[1],dBc(ch[0],ch[1]),pil[0],pil[1]);
      printf("data %u : rxF - > (%d,%d) (%d)\n",pilot_cnt+2,rxF[2],rxF[3],dBc(rxF[2],rxF[3]));
364 365 366 367 368 369
#endif
      multadd_real_vector_complex_scalar(fr,
                                         ch,
                                         ul_ch,
                                         8);

370

371 372
      // check if PRB crosses DC and improve estimates around DC
      if ((bwp_start_subcarrier < gNB->frame_parms.ofdm_symbol_size) && (bwp_start_subcarrier+nb_rb_pusch*12 >= gNB->frame_parms.ofdm_symbol_size)) {
373
        ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
374 375 376 377 378 379 380 381
        uint16_t idxDC = 2*(gNB->frame_parms.ofdm_symbol_size - bwp_start_subcarrier);
        uint16_t idxPil = idxDC/2;
        re_offset = k;
        pil = (int16_t *)&pilot[0];
        pil += (idxPil-2);
        ul_ch += (idxDC-4);
        ul_ch = memset(ul_ch, 0, sizeof(int16_t)*10);
        re_offset = (re_offset+idxDC/2-2) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
382
        rxF   = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)];
383 384
        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);
385 386 387 388 389 390 391 392

        // for proper allignment of SIMD vectors
        if((gNB->frame_parms.N_RB_UL&1)==0) {

          multadd_real_vector_complex_scalar(fdcl,
                                             ch,
                                             ul_ch-4,
                                             8);
393
        
394 395 396 397 398
          pil += 4;
          re_offset = (re_offset+4) % 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);
399
        
400 401 402 403 404 405 406 407 408 409
          multadd_real_vector_complex_scalar(fdcr,
                                             ch,
                                             ul_ch-4,
                                             8);
        }
        else {
          multadd_real_vector_complex_scalar(fdclh,
                                             ch,
                                             ul_ch,
                                             8);
410
        
411 412
          pil += 4;
          re_offset = (re_offset+4) % gNB->frame_parms.ofdm_symbol_size;
Eurecom's avatar
Eurecom committed
413
          rxF   = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)];
414 415
          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);
416
        
417 418 419 420 421
          multadd_real_vector_complex_scalar(fdcrh,
                                             ch,
                                             ul_ch,
                                             8);
        }
422
      }
423
#ifdef DEBUG_PUSCH
424
      ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
425 426 427 428 429
      for(uint16_t idxP=0; idxP<ceil((float)nb_rb_pusch*12/8); idxP++) {
        for(uint8_t idxI=0; idxI<16; idxI+=2) {
          printf("%d\t%d\t",ul_ch[idxP*16+idxI],ul_ch[idxP*16+idxI+1]);
        }
        printf("%d\n",idxP);
430 431
      }
#endif    
432 433
    }
    else { //pusch_dmrs_type2  |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d|
434 435 436

      // Treat first DMRS specially (left edge)

Eurecom's avatar
Eurecom committed
437
        rxF   = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)];
438 439 440 441 442 443 444 445 446 447 448

        ul_ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
        ul_ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);

        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){

Eurecom's avatar
Eurecom committed
449
          rxF   = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)];
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466

          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);

          ul_ch[0] = ch_l[0];
          ul_ch[1] = ch_l[1];

          pil+=2;
          ul_ch+=2;
          ch_offset++;

          multadd_real_four_symbols_vector_complex_scalar(filt8_ml2,
                                                          ch_l,
                                                          ul_ch);

          re_offset = (re_offset+5)%gNB->frame_parms.ofdm_symbol_size;

Eurecom's avatar
Eurecom committed
467
          rxF   = (int16_t *)&rxdataF[aarx][soffset+symbol_offset+nushift+re_offset];
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494

          ch_r[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
          ch_r[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);


          multadd_real_four_symbols_vector_complex_scalar(filt8_mr2,
                                                          ch_r,
                                                          ul_ch);

          //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[0] = ch_r[0];
          ul_ch[1] = ch_r[1];

          pil+=2;
          ul_ch+=2;
          ch_offset++;
          re_offset = (re_offset + 1)%gNB->frame_parms.ofdm_symbol_size;

        }

        // Treat last pilot specially (right edge)

Eurecom's avatar
Eurecom committed
495
        rxF   = (int16_t *)&rxdataF[aarx][soffset+(symbol_offset+nushift+re_offset)];
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513

        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);

        ul_ch[0] = ch_l[0];
        ul_ch[1] = ch_l[1];

        ul_ch+=2;
        ch_offset++;

        multadd_real_four_symbols_vector_complex_scalar(filt8_rr1,
                                                        ch_l,
                                                        ul_ch);

        multadd_real_four_symbols_vector_complex_scalar(filt8_rr2,
                                                        ch_r,
                                                        ul_ch);

514
        ul_ch_128 = (__m128i *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset];
515 516

        ul_ch_128[0] = _mm_slli_epi16 (ul_ch_128[0], 2);
517
    }
518 519


520
    // Convert to time domain
521

522
    switch (gNB->frame_parms.ofdm_symbol_size) {
523
        case 128:
frtabu's avatar
frtabu committed
524
          idft(IDFT_128,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
525 526 527 528 529
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;

        case 256:
frtabu's avatar
frtabu committed
530
          idft(IDFT_256,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
531 532 533 534 535
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;

        case 512:
frtabu's avatar
frtabu committed
536
          idft(IDFT_512,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
537 538 539 540 541
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;

        case 1024:
frtabu's avatar
frtabu committed
542
          idft(IDFT_1024,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
543 544 545 546 547
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;

        case 1536:
frtabu's avatar
frtabu committed
548
          idft(IDFT_1536,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
549 550 551 552 553
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;

        case 2048:
frtabu's avatar
frtabu committed
554
          idft(IDFT_2048,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
555 556 557 558 559
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;

        case 4096:
frtabu's avatar
frtabu committed
560
          idft(IDFT_4096,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
561 562 563 564 565
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;

        case 8192:
frtabu's avatar
frtabu committed
566
          idft(IDFT_8192,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
567 568 569 570 571
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;

        default:
frtabu's avatar
frtabu committed
572
          idft(IDFT_512,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
573 574 575 576 577
                 (int16_t*) ul_ch_estimates_time[aarx],
                 1);
          break;
      }

578 579 580 581 582 583 584
  }

#ifdef DEBUG_CH
  fclose(debug_ch_est);
#endif

  return(0);
585
}
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609


/*******************************************************************
 *
 * NAME :         nr_pusch_ptrs_processing
 *
 * PARAMETERS :   gNB         : gNB data structure
 *                rel15_ul    : UL parameters
 *                UE_id       : UE ID
 *                nr_tti_rx   : slot rx TTI
 *            dmrs_symbol_flag: DMRS Symbol Flag
 *                symbol      : OFDM Symbol
 *                nb_re_pusch : PUSCH RE's
 *                nb_re_pusch : PUSCH RE's
 *
 * RETURN :       nothing
 *
 * DESCRIPTION :
 *  If ptrs is enabled process the symbol accordingly
 *  1) Estimate phase noise per PTRS symbol
 *  2) Interpolate PTRS estimated value in TD after all PTRS symbols
 *  3) Compensated DMRS based estimated signal with PTRS estimation for slot
 *********************************************************************/
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
610
                              NR_DL_FRAME_PARMS *frame_parms,
611 612 613 614 615 616 617
                              nfapi_nr_pusch_pdu_t *rel15_ul,
                              uint8_t ulsch_id,
                              uint8_t nr_tti_rx,
                              unsigned char symbol,
                              uint32_t nb_re_pusch)
{
  //#define DEBUG_UL_PTRS 1
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
  int16_t *phase_per_symbol = NULL;
  int32_t *ptrs_re_symbol   = NULL;
  int8_t   ret = 0;

  uint8_t  symbInSlot       = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
  uint8_t *startSymbIndex   = &rel15_ul->start_symbol_index;
  uint8_t *nbSymb           = &rel15_ul->nr_of_symbols;
  uint8_t  *L_ptrs          = &rel15_ul->pusch_ptrs.ptrs_time_density;
  uint8_t  *K_ptrs          = &rel15_ul->pusch_ptrs.ptrs_freq_density;
  uint16_t *dmrsSymbPos     = &rel15_ul->ul_dmrs_symb_pos;
  uint16_t *ptrsSymbPos     = &gNB->pusch_vars[ulsch_id]->ptrs_symbols;
  uint8_t  *ptrsSymbIdx     = &gNB->pusch_vars[ulsch_id]->ptrs_symbol_index;
  uint8_t  *dmrsConfigType  = &rel15_ul->dmrs_config_type;
  uint16_t *nb_rb           = &rel15_ul->rb_size;
  uint8_t  *ptrsReOffset    = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
633
  /* loop over antennas */
634
  for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
635
    phase_per_symbol = (int16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx];
636 637 638
    ptrs_re_symbol = &gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot;
    *ptrs_re_symbol = 0;
    phase_per_symbol[(2*symbol)+1] = 0; // Imag
639
    /* set DMRS estimates to 0 angle with magnitude 1 */
640
    if(is_dmrs_symbol(symbol,*dmrsSymbPos)) {
641 642 643 644 645 646
      /* set DMRS real estimation to 32767 */
      phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767
#ifdef DEBUG_UL_PTRS
      printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]);
#endif
    }
647
    else {// real ptrs value is set to 0
648 649 650
      phase_per_symbol[2*symbol] = 0; // Real
    }

651
    if(symbol == *startSymbIndex) {
652 653 654 655 656 657
      *ptrsSymbPos = 0;
      set_ptrs_symb_idx(ptrsSymbPos,
                        *nbSymb,
                        *startSymbIndex,
                        1<< *L_ptrs,
                        *dmrsSymbPos);
658
    }
659
    /* if not PTRS symbol set current ptrs symbol index to zero*/
660
    *ptrsSymbIdx = 0;
661
    /* Check if current symbol contains PTRS */
662
    if(is_ptrs_symbol(symbol, *ptrsSymbPos)) {
663
      *ptrsSymbIdx = symbol;
664
      /*------------------------------------------------------------------------------------------------------- */
665
      /* 1) Estimate common phase error per PTRS symbol                                                                */
666
      /*------------------------------------------------------------------------------------------------------- */
667 668 669 670 671 672 673 674 675
      nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb,
                             rel15_ul->rnti,
                             (int16_t *)&gNB->pusch_vars[ulsch_id]->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch],
                             nr_tti_rx,
                             symbol,frame_parms->ofdm_symbol_size,
                             (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)],
                             gNB->nr_gold_pusch_dmrs[rel15_ul->scid][nr_tti_rx][symbol],
                             &phase_per_symbol[2* symbol],
                             ptrs_re_symbol);
676 677
    }
    /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/
678
    if(symbol == (symbInSlot -1)) {
679 680 681 682
      /*------------------------------------------------------------------------------------------------------- */
      /* 2) Interpolate PTRS estimated value in TD */
      /*------------------------------------------------------------------------------------------------------- */
      /* If L-PTRS is > 0 then we need interpolation */
683
      if(*L_ptrs > 0) {
684
        ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb);
685
        if(ret != 0) {
686
          LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
687
        }
688
      }
689
#ifdef DEBUG_UL_PTRS
690 691
      LOG_M("ptrsEstUl.m","est",gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
      LOG_M("rxdataF_bf_ptrs_comp_ul.m","bf_ptrs_cmp",
692 693
            &gNB->pusch_vars[0]->rxdataF_comp[aarx][rel15_ul->start_symbol_index * NR_NB_SC_PER_RB * rel15_ul->rb_size],
            rel15_ul->nr_of_symbols * NR_NB_SC_PER_RB * rel15_ul->rb_size,1,1);
694 695 696 697
#endif
      /*------------------------------------------------------------------------------------------------------- */
      /* 3) Compensated DMRS based estimated signal with PTRS estimation                                        */
      /*--------------------------------------------------------------------------------------------------------*/
698
      for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) {
699 700
        /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
        /* Skip rotation if the slot processing is wrong */
701
        if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) {
702
#ifdef DEBUG_UL_PTRS
703
          printf("[PHY][UL][PTRS]: Rotate Symbol %2d with  %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]);
704
#endif
705 706 707 708 709 710 711 712
          rotate_cpx_vector((int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)],
                            &phase_per_symbol[2* i],
                            (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)],
                            ((*nb_rb) * NR_NB_SC_PER_RB), 15);
        }// if not DMRS Symbol
      }// symbol loop
    }// last symbol check
  }//Antenna loop
713
}