pmch.c 35.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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
 */
ghaddab's avatar
ghaddab committed
21

22 23
#include "PHY/defs.h"
#include "PHY/extern.h"
24
#include "PHY/sse_intrin.h"
25

26
// Mask for identifying subframe for MBMS
27 28 29 30 31 32 33
#define MBSFN_TDD_SF3 0x80// for TDD
#define MBSFN_TDD_SF4 0x40
#define MBSFN_TDD_SF7 0x20
#define MBSFN_TDD_SF8 0x10
#define MBSFN_TDD_SF9 0x08

#include "PHY/defs.h"
34

35 36 37 38 39 40
#define MBSFN_FDD_SF1 0x80// for FDD
#define MBSFN_FDD_SF2 0x40
#define MBSFN_FDD_SF3 0x20
#define MBSFN_FDD_SF6 0x10
#define MBSFN_FDD_SF7 0x08
#define MBSFN_FDD_SF8 0x04
Raymond Knopp's avatar
 
Raymond Knopp committed
41 42


43

44
void dump_mch(PHY_VARS_UE *ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int subframe)
45
{
46 47 48

  unsigned int nsymb_pmch=12;
  char fname[32],vname[32];
49
  int N_RB_DL=ue->frame_parms.N_RB_DL;
50

51 52
  sprintf(fname,"mch_rxF_ext0.m");
  sprintf(vname,"pmch_rxF_ext0");
53
  write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb_pmch,1,1);
54 55
  sprintf(fname,"mch_ch_ext00.m");
  sprintf(vname,"pmch_ch_ext00");
56
  write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb_pmch,1,1);
57
  /*
58 59 60 61
    write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb_pmch,1,1);
    write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb_pmch,1,1);
    write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb_pmch,1,1);
    write_output("dlsch%d_rho.m","dl_rho",pdsch_vars[eNB_id]->rho[0],12*N_RB_DL*nsymb_pmch,1,1);
62 63 64
  */
  sprintf(fname,"mch_rxF_comp0.m");
  sprintf(vname,"pmch_rxF_comp0");
65
  write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb_pmch,1,1);
66 67
  sprintf(fname,"mch_rxF_llr.m");
  sprintf(vname,"pmch_llr");
68
  write_output(fname,vname, ue->pdsch_vars_MCH[eNB_id]->llr[0],coded_bits_per_codeword,1,0);
69 70
  sprintf(fname,"mch_mag1.m");
  sprintf(vname,"pmch_mag1");
71
  write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb_pmch,1,1);
72 73
  sprintf(fname,"mch_mag2.m");
  sprintf(vname,"pmch_mag2");
74
  write_output(fname,vname,ue->pdsch_vars_MCH[eNB_id]->dl_ch_magb0[0],12*N_RB_DL*nsymb_pmch,1,1);
75 76

  write_output("mch00_ch0.m","pmch00_ch0",
77
               &(ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id][0][0]),
78
               ue->frame_parms.ofdm_symbol_size*12,1,1);
79 80

  write_output("rxsig_mch.m","rxs_mch",
81 82
               &ue->common_vars.rxdata[0][subframe*ue->frame_parms.samples_per_tti],
               ue->frame_parms.samples_per_tti,1,1);
83

Raymond Knopp's avatar
 
Raymond Knopp committed
84 85
  if (PHY_vars_eNB_g)
    write_output("txsig_mch.m","txs_mch",
86 87
                 &PHY_vars_eNB_g[0][0]->common_vars.txdata[0][0][subframe*ue->frame_parms.samples_per_tti],
                 ue->frame_parms.samples_per_tti,1,1);
88 89
}

90 91
int is_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_parms)
{
92 93

  uint32_t period;
94
  uint8_t i;
95

Raymond Knopp's avatar
 
Raymond Knopp committed
96
  //  LOG_D(PHY,"is_pmch_subframe: frame %d, subframe %d, num_MBSFN_config %d\n",
97
  //  frame,subframe,frame_parms->num_MBSFN_config);
Raymond Knopp's avatar
 
Raymond Knopp committed
98

99 100
  for (i=0; i<frame_parms->num_MBSFN_config; i++) {  // we have at least one MBSFN configuration
    period = 1<<frame_parms->MBSFN_config[i].radioframeAllocationPeriod;
101

102 103
    if ((frame % period) == frame_parms->MBSFN_config[i].radioframeAllocationOffset) {
      if (frame_parms->MBSFN_config[i].fourFrames_flag == 0) {
104 105
        if (frame_parms->frame_type == FDD) {
          switch (subframe) {
106

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
          case 1:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_FDD_SF1) > 0)
              return(1);

            break;

          case 2:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_FDD_SF2) > 0)
              return(1);

            break;

          case 3:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_FDD_SF3) > 0)
              return(1);

            break;

          case 6:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_FDD_SF6) > 0)
              return(1);

            break;

          case 7:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_FDD_SF7) > 0)
              return(1);

            break;

          case 8:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_FDD_SF8) > 0)
              return(1);

            break;
          }
        } else  {
          switch (subframe) {
          case 3:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_TDD_SF3) > 0)
              return(1);

            break;

          case 4:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_TDD_SF4) > 0)
              return(1);

            break;

          case 7:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_TDD_SF7) > 0)
              return(1);

            break;

          case 8:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_TDD_SF8) > 0)
              return(1);

            break;

          case 9:
            if ((frame_parms->MBSFN_config[i].mbsfn_SubframeConfig & MBSFN_TDD_SF9) > 0)
              return(1);

            break;
          }
        }

      } else { // handle 4 frames case
178 179

      }
180
    }
181
  }
182

183
  return(0);
184
}
185

186
void fill_eNB_dlsch_MCH(PHY_VARS_eNB *eNB,int mcs,int ndi,int rvidx)
187
{
188

189 190
  LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_MCH;
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
191

192
  //  dlsch->rnti   = M_RNTI;
193
  dlsch->harq_processes[0]->mcs   = mcs;
194
  //  dlsch->harq_processes[0]->Ndi   = ndi;
195 196 197 198
  dlsch->harq_processes[0]->rvidx = rvidx;
  dlsch->harq_processes[0]->Nl    = 1;
  dlsch->harq_processes[0]->TBS   = TBStable[get_I_TBS(dlsch->harq_processes[0]->mcs)][frame_parms->N_RB_DL-1];
  dlsch->current_harq_pid = 0;
199
  dlsch->harq_processes[0]->nb_rb = frame_parms->N_RB_DL;
200 201 202

  switch(frame_parms->N_RB_DL) {
  case 6:
203
    dlsch->harq_processes[0]->rb_alloc[0] = 0x3f;
204
    break;
205

206
  case 25:
207
    dlsch->harq_processes[0]->rb_alloc[0] = 0x1ffffff;
208
    break;
209

210
  case 50:
211 212
    dlsch->harq_processes[0]->rb_alloc[0] = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc[1] = 0x3ffff;
213
    break;
214

215
  case 100:
216 217 218 219
    dlsch->harq_processes[0]->rb_alloc[0] = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc[1] = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc[2] = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc[3] = 0xf;
220 221
    break;
  }
222

223
  if (eNB->abstraction_flag) {
224 225 226 227 228 229 230 231
    eNB_transport_info[eNB->Mod_id][eNB->CC_id].cntl.pmch_flag=1;
    eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_pmch=1; // assumption: there is always one pmch in each SF
    eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_common_dci=0;
    eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_ue_spec_dci=0;
    eNB_transport_info[eNB->Mod_id][eNB->CC_id].dlsch_type[0]=5;// put at the reserved position for PMCH
    eNB_transport_info[eNB->Mod_id][eNB->CC_id].harq_pid[0]=0;
    eNB_transport_info[eNB->Mod_id][eNB->CC_id].ue_id[0]=255;//broadcast
    eNB_transport_info[eNB->Mod_id][eNB->CC_id].tbs[0]=dlsch->harq_processes[0]->TBS>>3;
232 233
  }

234 235
}

236
void fill_UE_dlsch_MCH(PHY_VARS_UE *ue,int mcs,int ndi,int rvidx,int eNB_id)
237
{
238

239 240
  LTE_UE_DLSCH_t *dlsch = ue->dlsch_MCH[eNB_id];
  LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
241

242
  //  dlsch->rnti   = M_RNTI;
243 244
  dlsch->harq_processes[0]->mcs   = mcs;
  dlsch->harq_processes[0]->rvidx = rvidx;
245
  //  dlsch->harq_processes[0]->Ndi   = ndi;
246 247 248 249
  dlsch->harq_processes[0]->Nl    = 1;
  dlsch->harq_processes[0]->TBS = TBStable[get_I_TBS(dlsch->harq_processes[0]->mcs)][frame_parms->N_RB_DL-1];
  dlsch->current_harq_pid = 0;
  dlsch->harq_processes[0]->nb_rb = frame_parms->N_RB_DL;
250

251 252
  switch(frame_parms->N_RB_DL) {
  case 6:
253 254
    dlsch->harq_processes[0]->rb_alloc_even[0] = 0x3f;
    dlsch->harq_processes[0]->rb_alloc_odd[0] = 0x3f;
255
    break;
256

257
  case 25:
258 259
    dlsch->harq_processes[0]->rb_alloc_even[0] = 0x1ffffff;
    dlsch->harq_processes[0]->rb_alloc_odd[0] = 0x1ffffff;
260
    break;
261

262
  case 50:
263 264 265 266
    dlsch->harq_processes[0]->rb_alloc_even[0] = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc_odd[0]  = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc_even[1] = 0x3ffff;
    dlsch->harq_processes[0]->rb_alloc_odd[1]  = 0x3ffff;
267
    break;
268

269
  case 100:
270 271 272 273 274 275 276 277
    dlsch->harq_processes[0]->rb_alloc_even[0] = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc_odd[0]  = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc_even[1] = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc_odd[1]  = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc_even[2] = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc_odd[2]  = 0xffffffff;
    dlsch->harq_processes[0]->rb_alloc_even[3] = 0xf;
    dlsch->harq_processes[0]->rb_alloc_odd[3]  = 0xf;
278 279 280 281
    break;
  }
}

282
void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a)
283
{
284 285

  int G;
286
  int subframe = proc->subframe_tx;
Raymond Knopp's avatar
 
Raymond Knopp committed
287

288
  if (eNB->abstraction_flag != 0) {
289 290
    if (eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]!=0)
      printf("[PHY][EMU] PMCH transport block position is different than zero %d \n", eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]);
291

292
    memcpy(eNB->dlsch_MCH->harq_processes[0]->b,
293
           a,
294
           eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
295
    LOG_D(PHY, "[eNB %d] dlsch_encoding_emul pmch , tbs is %d \n",
296 297
          eNB->Mod_id,
          eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
298

299
    memcpy(&eNB_transport_info[eNB->Mod_id][eNB->CC_id].transport_blocks[eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]],
300
           a,
301 302
           eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
    eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]+= eNB->dlsch_MCH->harq_processes[0]->TBS>>3;//=eNB_transport_info[eNB->Mod_id].tbs[0];
303
  } else {
304 305 306 307
    G = get_G(&eNB->frame_parms,
              eNB->frame_parms.N_RB_DL,
              eNB->dlsch_MCH->harq_processes[0]->rb_alloc,
              get_Qm(eNB->dlsch_MCH->harq_processes[0]->mcs),1,
308
              2,proc->frame_tx,subframe,0);
309

310
    generate_mbsfn_pilot(eNB,proc,
311
                         eNB->common_vars.txdataF[0],
312 313
                         AMP);

314

Raymond Knopp's avatar
Raymond Knopp committed
315 316
    if (dlsch_encoding(eNB,
		       a,
317
                       1,
318
                       eNB->dlsch_MCH,
319
                       proc->frame_tx,
320
                       subframe,
321 322 323
                       &eNB->dlsch_rate_matching_stats,
                       &eNB->dlsch_turbo_encoding_stats,
                       &eNB->dlsch_interleaving_stats
324
                      )<0)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
325
      mac_xface->macphy_exit("problem in dlsch_encoding");
326

327
    dlsch_scrambling(&eNB->frame_parms,1,eNB->dlsch_MCH,G,0,subframe<<1);
328 329


330
    mch_modulation(eNB->common_vars.txdataF[0],
331 332
                   AMP,
                   subframe,
333 334
                   &eNB->frame_parms,
                   eNB->dlsch_MCH);
335
  }
336 337

}
338 339

void mch_extract_rbs(int **rxdataF,
340 341 342 343 344 345 346
                     int **dl_ch_estimates,
                     int **rxdataF_ext,
                     int **dl_ch_estimates_ext,
                     unsigned char symbol,
                     unsigned char subframe,
                     LTE_DL_FRAME_PARMS *frame_parms)
{
347 348 349 350 351 352 353 354

  int pilots=0,i,j,offset,aarx;

  //  printf("Extracting PMCH: symbol %d\n",symbol);
  if ((symbol==2)||
      (symbol==10)) {
    pilots = 1;
    offset = 1;
355
  } else if (symbol==6) {
356 357 358 359 360
    pilots = 1;
    offset = 0;
  }


361
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
362 363

    if (pilots==1) {
364 365 366 367 368 369 370 371 372
      for (i=offset,j=0; i<frame_parms->N_RB_DL*6; i+=2,j++) {
        /*  printf("MCH with pilots: i %d, j %d => %d,%d\n",i,j,
               *(int16_t*)&rxdataF[aarx][i+frame_parms->first_carrier_offset + (symbol*frame_parms->ofdm_symbol_size)],
               *(int16_t*)(1+&rxdataF[aarx][i+frame_parms->first_carrier_offset + (symbol*frame_parms->ofdm_symbol_size)]));
               */
        rxdataF_ext[aarx][j+symbol*(frame_parms->N_RB_DL*12)]                                  = rxdataF[aarx][i+frame_parms->first_carrier_offset + (symbol*frame_parms->ofdm_symbol_size)];
        rxdataF_ext[aarx][(frame_parms->N_RB_DL*3)+j+symbol*(frame_parms->N_RB_DL*12)]         = rxdataF[aarx][i+1+ (symbol*frame_parms->ofdm_symbol_size)];
        dl_ch_estimates_ext[aarx][j+symbol*(frame_parms->N_RB_DL*12)]                          = dl_ch_estimates[aarx][i+(symbol*frame_parms->ofdm_symbol_size)];
        dl_ch_estimates_ext[aarx][(frame_parms->N_RB_DL*3)+j+symbol*(frame_parms->N_RB_DL*12)] = dl_ch_estimates[aarx][i+(frame_parms->N_RB_DL*6)+(symbol*frame_parms->ofdm_symbol_size)];
373
      }
374
    } else {
375

376
      memcpy((void*)&rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)],
377 378
             (void*)&rxdataF[aarx][frame_parms->first_carrier_offset + (symbol*frame_parms->ofdm_symbol_size)],
             frame_parms->N_RB_DL*24);
379
      memcpy((void*)&rxdataF_ext[aarx][(frame_parms->N_RB_DL*6) + symbol*(frame_parms->N_RB_DL*12)],
380 381
             (void*)&rxdataF[aarx][1 + (symbol*frame_parms->ofdm_symbol_size)],
             frame_parms->N_RB_DL*24);
382
      memcpy((void*)&dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)],
383 384
             (void*)&dl_ch_estimates[aarx][(symbol*frame_parms->ofdm_symbol_size)],
             frame_parms->N_RB_DL*48);
385

386 387 388 389 390 391 392 393 394
    }

  }



}

void mch_channel_level(int **dl_ch_estimates_ext,
395 396 397 398 399
                       LTE_DL_FRAME_PARMS *frame_parms,
                       int *avg,
                       uint8_t symbol,
                       unsigned short nb_rb)
{
400 401

  int i,aarx,nre;
402
#if defined(__x86_64__) || defined(__i386__)
403
  __m128i *dl_ch128,avg128;
404 405 406
#elif defined(__arm__)
  int32x4_t avg128; 
#endif
407
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
408 409
#if defined(__x86_64__) || defined(__i386__)
   //clear average level
410
    avg128 = _mm_setzero_si128();
411
    // 5 is always a symbol with no pilots for both normal and extended prefix
412

413
    dl_ch128=(__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12];
414 415
#elif defined(__arm__)

416

417
#endif
418 419 420 421 422
    if ((symbol == 2) || (symbol == 6) || (symbol == 10))
      nre = (frame_parms->N_RB_DL*6);
    else
      nre = (frame_parms->N_RB_DL*12);

423
    for (i=0; i<(nre>>2); i++) {
424
#if defined(__x86_64__) || defined(__i386__)
425
      avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
426 427 428
#elif defined(__arm__)

#endif
429
    }
430 431 432 433 434 435 436 437 438

    avg[aarx] = (((int*)&avg128)[0] +
                 ((int*)&avg128)[1] +
                 ((int*)&avg128)[2] +
                 ((int*)&avg128)[3])/nre;

    //            printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
  }

439
#if defined(__x86_64__) || defined(__i386__)
440 441
  _mm_empty();
  _m_empty();
442
#endif
443 444 445
}

void mch_channel_compensation(int **rxdataF_ext,
446 447 448 449 450 451 452 453 454
                              int **dl_ch_estimates_ext,
                              int **dl_ch_mag,
                              int **dl_ch_magb,
                              int **rxdataF_comp,
                              LTE_DL_FRAME_PARMS *frame_parms,
                              unsigned char symbol,
                              unsigned char mod_order,
                              unsigned char output_shift)
{
455 456

  int aarx,nre,i;
457
#if defined(__x86_64__) || defined(__i386__)
458 459
  __m128i *dl_ch128,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128;
  __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b;
460
#elif defined(__arm__)
461

462
#endif
463 464 465 466 467
  if ((symbol == 2) || (symbol == 6) || (symbol == 10))
    nre = frame_parms->N_RB_DL*6;
  else
    nre = frame_parms->N_RB_DL*12;

468
#if defined(__x86_64__) || defined(__i386__)
469 470 471
  if (mod_order == 4) {
    QAM_amp128 = _mm_set1_epi16(QAM16_n1);  // 2/sqrt(10)
    QAM_amp128b = _mm_setzero_si128();
472 473
  } else if (mod_order == 6) {
    QAM_amp128  = _mm_set1_epi16(QAM64_n1); //
474 475
    QAM_amp128b = _mm_set1_epi16(QAM64_n2);
  }
476
#elif defined(__arm__)
477

478
#endif
479 480

  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
481

482 483
#if defined(__x86_64__) || defined(__i386__)

484 485 486 487 488
    dl_ch128          = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128      = (__m128i *)&dl_ch_mag[aarx][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128b     = (__m128i *)&dl_ch_magb[aarx][symbol*frame_parms->N_RB_DL*12];
    rxdataF128        = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12];
    rxdataF_comp128   = (__m128i *)&rxdataF_comp[aarx][symbol*frame_parms->N_RB_DL*12];
489
#elif defined(__arm__)
490

491
#endif
492 493 494 495

    for (i=0; i<(nre>>2); i+=2) {
      if (mod_order>2) {
        // get channel amplitude if not QPSK
496
#if defined(__x86_64__) || defined(__i386__)
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525

        mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128[0]);
        mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);

        mmtmpD1 = _mm_madd_epi16(dl_ch128[1],dl_ch128[1]);
        mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);

        mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1);

        // store channel magnitude here in a new field of dlsch

        dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0);
        dl_ch_mag128b[0] = dl_ch_mag128[0];
        dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128);
        dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1);

        dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0);
        dl_ch_mag128b[1] = dl_ch_mag128[1];
        dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128);
        dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1);


        dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b);
        dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1);


        dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b);
        dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1);

526 527 528
#elif defined(__arm__)

#endif
529
      }
530

531 532
#if defined(__x86_64__) || defined(__i386__)

533 534
      // multiply by conjugated channel
      mmtmpD0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]);
535 536
      //  print_ints("re",&mmtmpD0);

537 538 539 540
      // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
      mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1));
      mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
      mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]);
541
      //  print_ints("im",&mmtmpD1);
542 543 544
      mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]);
      // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
      mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
545
      //  print_ints("re(shift)",&mmtmpD0);
546
      mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
547
      //  print_ints("im(shift)",&mmtmpD1);
548 549
      mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
      mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
550 551
      //        print_ints("c0",&mmtmpD2);
      //  print_ints("c1",&mmtmpD3);
552
      rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
553 554 555 556
      //  print_shorts("rx:",rxdataF128);
      //  print_shorts("ch:",dl_ch128);
      //  print_shorts("pack:",rxdataF_comp128);

557 558 559 560 561 562 563 564 565 566 567 568
      // multiply by conjugated channel
      mmtmpD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]);
      // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
      mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1));
      mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
      mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate);
      mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]);
      // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
      mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
      mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
      mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
      mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
569

570
      rxdataF_comp128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
571 572 573 574
      //  print_shorts("rx:",rxdataF128+1);
      //  print_shorts("ch:",dl_ch128+1);
      //  print_shorts("pack:",rxdataF_comp128+1);

575 576 577 578 579
      dl_ch128+=2;
      dl_ch_mag128+=2;
      dl_ch_mag128b+=2;
      rxdataF128+=2;
      rxdataF_comp128+=2;
580

581
#elif defined(__arm__)
582

583
#endif
584 585
    }
  }
586

587
#if defined(__x86_64__) || defined(__i386__)
588 589
  _mm_empty();
  _m_empty();
590 591
#endif

592 593 594
}

void mch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms,
595 596 597 598 599 600
                       int **rxdataF_comp,
                       int **dl_ch_mag,
                       int **dl_ch_magb,
                       unsigned char symbol)
{

601 602

  int i;
603
#if defined(__x86_64__) || defined(__i386__)
604
  __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b;
605 606 607
#elif defined(__arm__)
  int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b;
#endif
608
  if (frame_parms->nb_antennas_rx>1) {
609

610 611
#if defined(__x86_64__) || defined(__i386__)

612 613 614 615 616 617 618
    rxdataF_comp128_0   = (__m128i *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12];
    rxdataF_comp128_1   = (__m128i *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128_0      = (__m128i *)&dl_ch_mag[0][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128_1      = (__m128i *)&dl_ch_mag[1][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128_0b     = (__m128i *)&dl_ch_magb[0][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128_1b     = (__m128i *)&dl_ch_magb[1][symbol*frame_parms->N_RB_DL*12];

619 620 621 622 623 624 625 626 627
#elif defined(__arm__)
    rxdataF_comp128_0   = (int16x8_t *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12];
    rxdataF_comp128_1   = (int16x8_t *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128_0      = (int16x8_t *)&dl_ch_mag[0][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128_1      = (int16x8_t *)&dl_ch_mag[1][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128_0b     = (int16x8_t *)&dl_ch_magb[0][symbol*frame_parms->N_RB_DL*12];
    dl_ch_mag128_1b     = (int16x8_t *)&dl_ch_magb[1][symbol*frame_parms->N_RB_DL*12];

#endif
628
    // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
629
    for (i=0; i<frame_parms->N_RB_DL*3; i++) {
630
#if defined(__x86_64__) || defined(__i386__)
631 632 633
      rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1));
      dl_ch_mag128_0[i]    = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0[i],1),_mm_srai_epi16(dl_ch_mag128_1[i],1));
      dl_ch_mag128_0b[i]   = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0b[i],1),_mm_srai_epi16(dl_ch_mag128_1b[i],1));
634 635 636 637 638
#elif defined(__arm__)
      rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);
      dl_ch_mag128_0[i]    = vhaddq_s16(dl_ch_mag128_0[i],dl_ch_mag128_1[i]);
      dl_ch_mag128_0b[i]   = vhaddq_s16(dl_ch_mag128_0b[i],dl_ch_mag128_1b[i]);
#endif
639 640
    }
  }
641
#if defined(__x86_64__) || defined(__i386__)
642 643
  _mm_empty();
  _m_empty();
644
#endif
645 646 647
}

int mch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
648 649 650 651 652
                 int **rxdataF_comp,
                 short *dlsch_llr,
                 unsigned char symbol,
                 short **llr32p)
{
653

654 655
  uint32_t *rxF = (uint32_t*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
  uint32_t *llr32;
656 657 658
  int i,len;

  if (symbol==2) {
659 660 661
    llr32 = (uint32_t*)dlsch_llr;
  } else {
    llr32 = (uint32_t*)(*llr32p);
662
  }
663

664
  if (!llr32) {
665 666 667
    msg("dlsch_qpsk_llr: llr is null, symbol %d, llr32=%p\n",symbol, llr32);
    return(-1);
  }
668 669 670 671


  if ((symbol==2) || (symbol==6) || (symbol==10)) {
    len = frame_parms->N_RB_DL*6;
672
  } else {
673 674
    len = frame_parms->N_RB_DL*12;
  }
675

676
  //  printf("dlsch_qpsk_llr: symbol %d,len %d,pbch_pss_sss_adjust %d\n",symbol,len,pbch_pss_sss_adjust);
677 678 679 680
  for (i=0; i<len; i++) {
    *llr32 = *rxF;
    rxF++;
    llr32++;
681 682 683 684
  }

  *llr32p = (short *)llr32;

685
#if defined(__x86_64__) || defined(__i386__)
686 687
  _mm_empty();
  _m_empty();
688
#endif
689 690 691 692 693 694 695 696 697

  return(0);
}

//----------------------------------------------------------------------------------------------
// 16-QAM
//----------------------------------------------------------------------------------------------

void mch_16qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
698 699 700 701 702 703 704
                   int **rxdataF_comp,
                   short *dlsch_llr,
                   int **dl_ch_mag,
                   unsigned char symbol,
                   int16_t **llr32p)
{

705
#if defined(__x86_64__) || defined(__i386__)
706 707 708
  __m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
  __m128i *ch_mag;
  __m128i llr128[2],xmm0;
709 710 711 712 713 714 715
  uint32_t *llr32;
#elif defined(__arm__)
  int16x8_t *rxF = (int16x8_t*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
  int16x8_t *ch_mag;
  int16x8_t llr128[2],xmm0;
  int16_t *llr16;
#endif
716 717 718
  int i,len;
  unsigned char len_mod4=0;

719
#if defined(__x86_64__) || defined(__i386__)
720 721 722 723 724
  if (symbol==2) {
    llr32 = (uint32_t*)dlsch_llr;
  } else {
    llr32 = (uint32_t*)*llr32p;
  }
725 726 727 728 729 730 731 732
#elif defined(__arm__)
  if (symbol==2) {
    llr16 = (int16_t*)dlsch_llr;
  } else {
    llr16 = (int16_t*)*llr32p;
  }
#endif
#if defined(__x86_64__) || defined(__i386__)
733
  ch_mag = (__m128i*)&dl_ch_mag[0][(symbol*frame_parms->N_RB_DL*12)];
734 735 736
#elif defined(__arm__)
  ch_mag = (int16x8_t*)&dl_ch_mag[0][(symbol*frame_parms->N_RB_DL*12)];
#endif
737 738 739 740 741 742 743
  if ((symbol==2) || (symbol==6) || (symbol==10)) {
    len = frame_parms->N_RB_DL*6;
  } else {
    len = frame_parms->N_RB_DL*12;
  }


744 745

  // update output pointer according to number of REs in this symbol (<<2 because 4 bits per RE)
746 747 748 749 750 751 752 753 754 755 756
  if (symbol==2)
    *llr32p = dlsch_llr + (len<<2);
  else
    *llr32p += (len<<2);

  len_mod4 = len&3;
  len>>=2;  // length in quad words (4 REs)
  len+=(len_mod4==0 ? 0 : 1);

  for (i=0; i<len; i++) {

757
#if defined(__x86_64__) || defined(__i386__)
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
    xmm0 = _mm_abs_epi16(rxF[i]);
    xmm0 = _mm_subs_epi16(ch_mag[i],xmm0);

    // lambda_1=y_R, lambda_2=|y_R|-|h|^2, lamda_3=y_I, lambda_4=|y_I|-|h|^2
    llr128[0] = _mm_unpacklo_epi32(rxF[i],xmm0);
    llr128[1] = _mm_unpackhi_epi32(rxF[i],xmm0);
    llr32[0] = ((uint32_t *)&llr128[0])[0];
    llr32[1] = ((uint32_t *)&llr128[0])[1];
    llr32[2] = ((uint32_t *)&llr128[0])[2];
    llr32[3] = ((uint32_t *)&llr128[0])[3];
    llr32[4] = ((uint32_t *)&llr128[1])[0];
    llr32[5] = ((uint32_t *)&llr128[1])[1];
    llr32[6] = ((uint32_t *)&llr128[1])[2];
    llr32[7] = ((uint32_t *)&llr128[1])[3];
    llr32+=8;
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798

#elif defined(__arm__)
    xmm0 = vabsq_s16(rxF[i]);
    xmm0 = vsubq_s16(ch_mag[i],xmm0);

    // lambda_1=y_R, lambda_2=|y_R|-|h|^2, lamda_3=y_I, lambda_4=|y_I|-|h|^2

    llr16[0] = vgetq_lane_s16(rxF[i],0);
    llr16[1] = vgetq_lane_s16(xmm0,0);
    llr16[2] = vgetq_lane_s16(rxF[i],1);
    llr16[3] = vgetq_lane_s16(xmm0,1);
    llr16[4] = vgetq_lane_s16(rxF[i],2);
    llr16[5] = vgetq_lane_s16(xmm0,2);
    llr16[6] = vgetq_lane_s16(rxF[i],2);
    llr16[7] = vgetq_lane_s16(xmm0,3);
    llr16[8] = vgetq_lane_s16(rxF[i],4);
    llr16[9] = vgetq_lane_s16(xmm0,4);
    llr16[10] = vgetq_lane_s16(rxF[i],5);
    llr16[11] = vgetq_lane_s16(xmm0,5);
    llr16[12] = vgetq_lane_s16(rxF[i],6);
    llr16[13] = vgetq_lane_s16(xmm0,6);
    llr16[14] = vgetq_lane_s16(rxF[i],7);
    llr16[15] = vgetq_lane_s16(xmm0,7);
    llr16+=16;
#endif

799
  }
800

801
#if defined(__x86_64__) || defined(__i386__)
802 803
  _mm_empty();
  _m_empty();
804
#endif
805 806 807 808 809 810 811
}

//----------------------------------------------------------------------------------------------
// 64-QAM
//----------------------------------------------------------------------------------------------

void mch_64qam_llr(LTE_DL_FRAME_PARMS *frame_parms,
812 813 814 815 816 817 818
                   int **rxdataF_comp,
                   short *dlsch_llr,
                   int **dl_ch_mag,
                   int **dl_ch_magb,
                   unsigned char symbol,
                   short **llr_save)
{
819

820
#if defined(__x86_64__) || defined(__i386__)
Raymond Knopp's avatar
 
Raymond Knopp committed
821 822
  __m128i xmm1,xmm2,*ch_mag,*ch_magb;
  __m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
823 824 825 826
#elif defined(__arm__)
  int16x8_t xmm1,xmm2,*ch_mag,*ch_magb;
  int16x8_t *rxF = (int16x8_t*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
#endif
827

828
  int i,len,len2;
829
  //   int j=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
830 831
  unsigned char len_mod4;
  short *llr;
832
  int16_t *llr2;
833

Raymond Knopp's avatar
 
Raymond Knopp committed
834 835 836 837
  if (symbol==2)
    llr = dlsch_llr;
  else
    llr = *llr_save;
838

839
#if defined(__x86_64__) || defined(__i386__)
Raymond Knopp's avatar
 
Raymond Knopp committed
840 841
  ch_mag = (__m128i*)&dl_ch_mag[0][(symbol*frame_parms->N_RB_DL*12)];
  ch_magb = (__m128i*)&dl_ch_magb[0][(symbol*frame_parms->N_RB_DL*12)];
842 843 844 845
#elif defined(__arm__)
  ch_mag = (int16x8_t*)&dl_ch_mag[0][(symbol*frame_parms->N_RB_DL*12)];
  ch_magb = (int16x8_t*)&dl_ch_magb[0][(symbol*frame_parms->N_RB_DL*12)];
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
846 847
  if ((symbol==2) || (symbol==6) || (symbol==10)) {
    len = frame_parms->N_RB_DL*6;
848
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
849 850
    len = frame_parms->N_RB_DL*12;
  }
851 852


Raymond Knopp's avatar
 
Raymond Knopp committed
853 854
  llr2 = llr;
  llr += (len*6);
855

Raymond Knopp's avatar
 
Raymond Knopp committed
856 857 858
  len_mod4 =len&3;
  len2=len>>2;  // length in quad words (4 REs)
  len2+=(len_mod4?0:1);
859 860 861


  for (i=0; i<len2; i++) {
862
#if defined(__x86_64__) || defined(__i386__)
Raymond Knopp's avatar
 
Raymond Knopp committed
863 864 865 866
    xmm1 = _mm_abs_epi16(rxF[i]);
    xmm1  = _mm_subs_epi16(ch_mag[i],xmm1);
    xmm2 = _mm_abs_epi16(xmm1);
    xmm2 = _mm_subs_epi16(ch_magb[i],xmm2);
867 868 869 870 871 872 873
#elif defined(__arm__)
    xmm1 = vabsq_s16(rxF[i]);
    xmm1 = vsubq_s16(ch_mag[i],xmm1);
    xmm2 = vabsq_s16(xmm1);
    xmm2 = vsubq_s16(ch_magb[i],xmm2);
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
874 875 876 877 878
    /*
      printf("pmch i: %d => mag (%d,%d) (%d,%d)\n",i,((short *)&ch_mag[i])[0],((short *)&ch_magb[i])[0],
      ((short *)&rxF[i])[0],((short *)&rxF[i])[1]);
    */
    // loop over all LLRs in quad word (24 coded bits)
879 880
    /*
    for (j=0;j<8;j+=2) {
Raymond Knopp's avatar
 
Raymond Knopp committed
881 882 883 884 885 886
      llr2[0] = ((short *)&rxF[i])[j];
      llr2[1] = ((short *)&rxF[i])[j+1];
      llr2[2] = _mm_extract_epi16(xmm1,j);
      llr2[3] = _mm_extract_epi16(xmm1,j+1);//((short *)&xmm1)[j+1];
      llr2[4] = _mm_extract_epi16(xmm2,j);//((short *)&xmm2)[j];
      llr2[5] = _mm_extract_epi16(xmm2,j+1);//((short *)&xmm2)[j+1];
887

Raymond Knopp's avatar
 
Raymond Knopp committed
888
      llr2+=6;
889
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
890
    */
891 892
    llr2[0] = ((short *)&rxF[i])[0];
    llr2[1] = ((short *)&rxF[i])[1];
893
#if defined(__x86_64__) || defined(__i386__)
894 895 896 897
    llr2[2] = _mm_extract_epi16(xmm1,0);
    llr2[3] = _mm_extract_epi16(xmm1,1);//((short *)&xmm1)[j+1];
    llr2[4] = _mm_extract_epi16(xmm2,0);//((short *)&xmm2)[j];
    llr2[5] = _mm_extract_epi16(xmm2,1);//((short *)&xmm2)[j+1];
898 899 900 901 902 903
#elif defined(__arm__)
    llr2[2] = vgetq_lane_s16(xmm1,0);
    llr2[3] = vgetq_lane_s16(xmm1,1);//((short *)&xmm1)[j+1];
    llr2[4] = vgetq_lane_s16(xmm2,0);//((short *)&xmm2)[j];
    llr2[5] = vgetq_lane_s16(xmm2,1);//((short *)&xmm2)[j+1];
#endif
904 905 906 907

    llr2+=6;
    llr2[0] = ((short *)&rxF[i])[2];
    llr2[1] = ((short *)&rxF[i])[3];
908
#if defined(__x86_64__) || defined(__i386__)
909 910 911 912
    llr2[2] = _mm_extract_epi16(xmm1,2);
    llr2[3] = _mm_extract_epi16(xmm1,3);//((short *)&xmm1)[j+1];
    llr2[4] = _mm_extract_epi16(xmm2,2);//((short *)&xmm2)[j];
    llr2[5] = _mm_extract_epi16(xmm2,3);//((short *)&xmm2)[j+1];
913 914 915 916 917 918
#elif defined(__arm__)
    llr2[2] = vgetq_lane_s16(xmm1,2);
    llr2[3] = vgetq_lane_s16(xmm1,3);//((short *)&xmm1)[j+1];
    llr2[4] = vgetq_lane_s16(xmm2,2);//((short *)&xmm2)[j];
    llr2[5] = vgetq_lane_s16(xmm2,3);//((short *)&xmm2)[j+1];
#endif
919 920 921
    llr2+=6;
    llr2[0] = ((short *)&rxF[i])[4];
    llr2[1] = ((short *)&rxF[i])[5];
922
#if defined(__x86_64__) || defined(__i386__)
923 924 925 926
    llr2[2] = _mm_extract_epi16(xmm1,4);
    llr2[3] = _mm_extract_epi16(xmm1,5);//((short *)&xmm1)[j+1];
    llr2[4] = _mm_extract_epi16(xmm2,4);//((short *)&xmm2)[j];
    llr2[5] = _mm_extract_epi16(xmm2,5);//((short *)&xmm2)[j+1];
927 928 929 930 931 932
#elif defined(__arm__)
    llr2[2] = vgetq_lane_s16(xmm1,4);
    llr2[3] = vgetq_lane_s16(xmm1,5);//((short *)&xmm1)[j+1];
    llr2[4] = vgetq_lane_s16(xmm2,4);//((short *)&xmm2)[j];
    llr2[5] = vgetq_lane_s16(xmm2,5);//((short *)&xmm2)[j+1];
#endif
933 934 935
    llr2+=6;
    llr2[0] = ((short *)&rxF[i])[6];
    llr2[1] = ((short *)&rxF[i])[7];
936
#if defined(__x86_64__) || defined(__i386__)
937 938 939 940
    llr2[2] = _mm_extract_epi16(xmm1,6);
    llr2[3] = _mm_extract_epi16(xmm1,7);//((short *)&xmm1)[j+1];
    llr2[4] = _mm_extract_epi16(xmm2,6);//((short *)&xmm2)[j];
    llr2[5] = _mm_extract_epi16(xmm2,7);//((short *)&xmm2)[j+1];
941 942 943 944 945 946
#elif defined(__arm__)
    llr2[2] = vgetq_lane_s16(xmm1,6);
    llr2[3] = vgetq_lane_s16(xmm1,7);//((short *)&xmm1)[j+1];
    llr2[4] = vgetq_lane_s16(xmm2,6);//((short *)&xmm2)[j];
    llr2[5] = vgetq_lane_s16(xmm2,7);//((short *)&xmm2)[j+1];
#endif
947
    llr2+=6;
Raymond Knopp's avatar
 
Raymond Knopp committed
948
  }
949

Raymond Knopp's avatar
 
Raymond Knopp committed
950
  *llr_save = llr;
951
#if defined(__x86_64__) || defined(__i386__)
Raymond Knopp's avatar
 
Raymond Knopp committed
952 953
  _mm_empty();
  _m_empty();
954
#endif
955 956 957
}

int avg_pmch[4];
958
int rx_pmch(PHY_VARS_UE *ue,
959 960 961 962
            unsigned char eNB_id,
            uint8_t subframe,
            unsigned char symbol)
{
963

964 965 966 967
  LTE_UE_COMMON *common_vars  = &ue->common_vars;
  LTE_UE_PDSCH **pdsch_vars   = &ue->pdsch_vars_MCH[eNB_id];
  LTE_DL_FRAME_PARMS *frame_parms    = &ue->frame_parms;
  LTE_UE_DLSCH_t   **dlsch        = &ue->dlsch_MCH[eNB_id];
968 969
  int avgs,aarx;

Raymond Knopp's avatar
 
Raymond Knopp committed
970 971
  //printf("*********************mch: symbol %d\n",symbol);

972 973
  mch_extract_rbs(common_vars->common_vars_rx_data_per_thread[subframe&0x1].rxdataF,
                  common_vars->common_vars_rx_data_per_thread[subframe&0x1].dl_ch_estimates[eNB_id],
974 975
                  pdsch_vars[eNB_id]->rxdataF_ext,
                  pdsch_vars[eNB_id]->dl_ch_estimates_ext,
976 977 978 979
                  symbol,
                  subframe,
                  frame_parms);

980
  if (symbol == 2) {
981
    mch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
982 983 984 985
                      frame_parms,
                      avg_pmch,
                      symbol,
                      frame_parms->N_RB_DL);
986 987
  }

988 989 990 991 992
  avgs = 0;

  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
    avgs = cmax(avgs,avg_pmch[aarx]);

993 994
  if (get_Qm(dlsch[0]->harq_processes[0]->mcs)==2)
    pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2) ;// + 2
995
  else
996
    pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2); // + 5;// + 2
997

998 999 1000 1001 1002
  mch_channel_compensation(pdsch_vars[eNB_id]->rxdataF_ext,
                           pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                           pdsch_vars[eNB_id]->dl_ch_mag0,
                           pdsch_vars[eNB_id]->dl_ch_magb0,
                           pdsch_vars[eNB_id]->rxdataF_comp0,
1003 1004
                           frame_parms,
                           symbol,
1005 1006
                           get_Qm(dlsch[0]->harq_processes[0]->mcs),
                           pdsch_vars[eNB_id]->log2_maxh);
1007 1008 1009 1010


  if (frame_parms->nb_antennas_rx > 1)
    mch_detection_mrc(frame_parms,
1011 1012 1013
                      pdsch_vars[eNB_id]->rxdataF_comp0,
                      pdsch_vars[eNB_id]->dl_ch_mag0,
                      pdsch_vars[eNB_id]->dl_ch_magb0,
1014 1015
                      symbol);

1016
  switch (get_Qm(dlsch[0]->harq_processes[0]->mcs)) {
1017 1018
  case 2 :
    mch_qpsk_llr(frame_parms,
1019 1020
                 pdsch_vars[eNB_id]->rxdataF_comp0,
                 pdsch_vars[eNB_id]->llr[0],
1021
                 symbol,
1022
                 pdsch_vars[eNB_id]->llr128);
1023 1024 1025 1026
    break;

  case 4:
    mch_16qam_llr(frame_parms,
1027 1028 1029
                  pdsch_vars[eNB_id]->rxdataF_comp0,
                  pdsch_vars[eNB_id]->llr[0],
                  pdsch_vars[eNB_id]->dl_ch_mag0,
1030
                  symbol,
1031
                  pdsch_vars[eNB_id]->llr128);
1032 1033 1034 1035
    break;

  case 6:
    mch_64qam_llr(frame_parms,
1036 1037 1038 1039
                  pdsch_vars[eNB_id]->rxdataF_comp0,
                  pdsch_vars[eNB_id]->llr[0],
                  pdsch_vars[eNB_id]->dl_ch_mag0,
                  pdsch_vars[eNB_id]->dl_ch_magb0,
1040
                  symbol,
1041
                  pdsch_vars[eNB_id]->llr128);
1042 1043 1044 1045
    break;
  }

  return(0);
1046 1047
}