phy_procedures_lte_eNb.c 70 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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
 */
21 22 23

/*! \file phy_procedures_lte_eNB.c
 * \brief Implementation of eNB procedures from 36.213 LTE specifications
24
 * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
25 26 27
 * \date 2011
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
29 30 31 32
 * \note
 * \warning
 */

33 34 35 36
#include "PHY/defs_eNB.h"
#include "PHY/phy_extern.h"
#include "SCHED/sched_eNB.h"
#include "SCHED/sched_common_extern.h"
knopp's avatar
knopp committed
37
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
38
#include "nfapi_interface.h"
39
#include "fapi_l1.h"
40 41 42
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

43 44
#include "T.h"

45
#include "assertions.h"
gauthier's avatar
gauthier committed
46
#include "msc.h"
47

48 49
#include <time.h>

50
#if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
51
#   include "intertask_interface.h"
52 53
#endif

54
extern uint8_t nfapi_mode;
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127



int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint8_t UE_id,uint8_t harq_pid, uint8_t bw_factor)
{

  uint32_t Nre,sumKr,MPR_x100,Kr,r;
  uint16_t beta_offset_pusch;

  DevAssert( UE_id < NUMBER_OF_UE_MAX+1 );
  DevAssert( harq_pid < 8 );

  Nre = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_initial *
        eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12;

  sumKr = 0;

  for (r=0; r<eNB->ulsch[UE_id]->harq_processes[harq_pid]->C; r++) {
    if (r<eNB->ulsch[UE_id]->harq_processes[harq_pid]->Cminus)
      Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kminus;
    else
      Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus;

    sumKr += Kr;
  }

  if (Nre==0)
    return(0);

  MPR_x100 = 100*sumKr/Nre;
  // Note: MPR=is the effective spectral efficiency of the PUSCH
  // FK 20140908 sumKr is only set after the ulsch_encoding

  beta_offset_pusch = 8;
  //(eNB->ulsch[UE_id]->harq_processes[harq_pid]->control_only == 1) ? eNB->ulsch[UE_id]->beta_offset_cqi_times8:8;

  DevAssert( UE_id < NUMBER_OF_UE_MAX );
//#warning "This condition happens sometimes. Need more investigation" // navid
  //DevAssert( MPR_x100/6 < 100 );

  if (1==1) { //eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled == 1) {
    // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch)
    if (bw_factor == 1) {
      uint8_t nb_rb = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb;
      return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)) + hundred_times_log10_NPRB[nb_rb-1];
    } else
      return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3));
  } else {
    return(0);
  }
}


int16_t get_hundred_times_delta_IF_mac(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t harq_pid)
{

  int8_t UE_id;

  if ((RC.eNB == NULL) || (module_idP > RC.nb_inst) || (CC_id > RC.nb_CC[module_idP])) {
    LOG_E(PHY,"get_UE_stats: No eNB found (or not allocated) for Mod_id %d,CC_id %d\n",module_idP,CC_id);
    return -1;
  }

  UE_id = find_ulsch( rnti, RC.eNB[module_idP][CC_id],SEARCH_EXIST);

  if (UE_id == -1) {
    // not found
    return 0;
  }

  return get_hundred_times_delta_IF_eNB( RC.eNB[module_idP][CC_id], UE_id, harq_pid, 0 );
}

128
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind);
129

knopp's avatar
knopp committed
130

131 132
lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subframe)
{
133

134 135 136 137 138
  return(subframe_select(&RC.eNB[Mod_id][CC_id]->frame_parms,subframe));

}

void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
139 140


Cedric Roux's avatar
Cedric Roux committed
141
#if defined(Rel10) || defined(Rel14)
knopp's avatar
knopp committed
142
  MCH_PDU *mch_pduP=NULL;
143
  //  uint8_t sync_area=255;
144
#endif
145

146
  int subframe = proc->subframe_tx;
147

knopp's avatar
knopp committed
148 149
  AssertFatal(1==0,"pmch not tested for the moment, exiting\n");

150 151 152 153 154 155
  // This is DL-Cell spec pilots in Control region
  generate_pilots_slot(eNB,
		       eNB->common_vars.txdataF,
		       AMP,
		       subframe<<1,1);

156
  
Cedric Roux's avatar
Cedric Roux committed
157
#if defined(Rel10) || defined(Rel14)
158 159
  // if mcch is active, send regardless of the node type: eNB or RN
  // when mcch is active, MAC sched does not allow MCCH and MTCH multiplexing
160
  /*
161 162
  mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id,
				    eNB->CC_id,
163
				    proc->frame_tx,
164
				    subframe);
165
  */
166 167 168 169 170 171 172 173 174 175
  if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0
    LOG_D(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n",
	  eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs,
	  eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
  else {
    LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n",
	  eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->sync_area,
	  (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment");
    mch_pduP = NULL;
  }
176 177
    
  if (mch_pduP) {
178
    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0);
179
    // Generate PMCH
180
    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload);
181
  } else {
182
    LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe);
knopp's avatar
knopp committed
183
  }
184
  
185
#endif
186
}
187

188
void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
189

190
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
191
  int **txdataF = eNB->common_vars.txdataF;
192
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
193

194
  //LOG_D(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?"); 
195

196
  // generate Cell-Specific Reference Signals for both slots
197 198 199 200 201 202 203
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
  generate_pilots_slot(eNB,
		       txdataF,
		       AMP,
		       subframe<<1,0);
  // check that 2nd slot is for DL
  if (subframe_select(fp,subframe) == SF_DL)
204 205 206
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
207 208 209 210
			 (subframe<<1)+1,0);
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0);
      
211

212
  // First half of PSS/SSS (FDD, slot 0)
knopp's avatar
knopp committed
213
  if (subframe == 0) {
214
    if (fp->frame_type == FDD) {
215 216 217 218 219 220 221 222 223 224 225
      generate_pss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   0);
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 5 : 4,
		   0);
      
226
    }
227
    
228 229


230 231 232
      
    /// First half of SSS (TDD, slot 1)
    
233
    if (fp->frame_type == TDD) {
234 235 236 237 238 239
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   1);
    }
240

241 242
    // generate PBCH (Physical Broadcast CHannel) info

243
    /// generate PBCH
244
    if ((frame&3)==0) {
245 246
      //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n");
      if (eNB->pbch_configured!=1) return;
247
      eNB->pbch_configured=0;
248
    }
249 250 251 252 253 254 255
    generate_pbch(&eNB->pbch,
		  txdataF,
		  AMP,
		  fp,
		  pbch_pdu,
		  frame&3);
  
256
  }
257
  else if ((subframe == 1) &&
258
	   (fp->frame_type == TDD)){
259 260 261 262 263
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
264
  }
265 266 267
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
268
	   (fp->frame_type == FDD)) {
269 270 271 272 273 274 275 276 277 278
    generate_pss(txdataF,
		 AMP,
		 &eNB->frame_parms,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 10);
    generate_sss(txdataF,
		 AMP,
		 &eNB->frame_parms,
		 (fp->Ncp==NORMAL) ? 5 : 4,
		 10);
279

280
  }
281

282 283
  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
284
	   (fp->frame_type == TDD)) {
285 286 287 288 289
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
knopp's avatar
knopp committed
290
  }
knopp's avatar
knopp committed
291

292 293
  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
294
	   (fp->frame_type == TDD)) { 
295 296 297 298 299 300
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }
knopp's avatar
knopp committed
301

302
}
knopp's avatar
knopp committed
303

304 305


306 307 308 309 310 311
void pdsch_procedures(PHY_VARS_eNB *eNB,
		      eNB_rxtx_proc_t *proc,
		      int harq_pid,
		      LTE_eNB_DLSCH_t *dlsch, 
		      LTE_eNB_DLSCH_t *dlsch1,
		      LTE_eNB_UE_stats *ue_stats,
312
		      int ra_flag) {
313

314 315
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
316 317
  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
  int input_buffer_length = dlsch_harq->TBS/8;
318
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
319

320
  if (dlsch->rnti == 0x02) {//frame < 200) {
321

322
    LOG_D(PHY,
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
	  "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", pdsch_start %d, G %d, nb_rb %"PRIu16", rb0 %x, rb1 %x, TBS %"PRIu16", pmi_alloc %"PRIx64", rv %"PRIu8" (round %"PRIu8")\n",
	  eNB->Mod_id, dlsch->rnti,harq_pid,
	  frame, subframe, input_buffer_length, dlsch_harq->pdsch_start,
	  get_G(fp,
		dlsch_harq->nb_rb,
		dlsch_harq->rb_alloc,
		dlsch_harq->Qm,
		dlsch_harq->Nl,
		dlsch_harq->pdsch_start,
		frame,
		subframe,
		dlsch_harq->mimo_mode==TM7?7:0),
	  dlsch_harq->nb_rb,
	  dlsch_harq->rb_alloc[0],
	  dlsch_harq->rb_alloc[1],
	  dlsch_harq->TBS,
	  pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	  dlsch_harq->rvidx,
	  dlsch_harq->round);
  }    
343
#if defined(MESSAGE_CHART_GENERATOR_PHY)
344 345 346
  MSC_LOG_TX_MESSAGE(
		     MSC_PHY_ENB,MSC_PHY_UE,
		     NULL,0,
347
		     "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", TBS %"PRIu16", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
348 349 350 351 352
		     frame, subframe,
		     input_buffer_length,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
353
			   dlsch_harq->Qm,
354
			   dlsch_harq->Nl,
355
			   dlsch_harq->pdsch_start,
356 357 358
			   frame,
			   subframe,
			   dlsch_harq->mimo_mode==TM7?7:0),
359
		     dlsch_harq->nb_rb,
360
		     dlsch_harq->TBS,
361 362 363 364
		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
		     dlsch_harq->rvidx,
		     dlsch_harq->round);
#endif
365 366
  
  
367
  if (ue_stats) ue_stats->dlsch_sliding_cnt++;
368
  
369 370 371
  if (dlsch_harq->round == 0) {
    if (ue_stats)
      ue_stats->dlsch_trials[harq_pid][0]++;
372 373 374 375 376 377 378 379
  } else {
    ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++;
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
#endif
#endif
  }
380 381


382 383
  LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n",
      dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0],dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round);
384
  // 36-212 
385 386 387 388 389 390 391 392 393 394
  if (nfapi_mode == 0 || nfapi_mode == 1) { // monolthic OR PNF - do not need turbo encoding on VNF

    if (dlsch_harq->pdu==NULL){
        LOG_E(PHY,"dlsch_harq->pdu == NULL SFN/SF:%04d%d dlsch[rnti:%x] dlsch_harq[pdu:%p pdsch_start:%d Qm:%d Nl:%d round:%d nb_rb:%d rb_alloc[0]:%d]\n", frame,subframe,dlsch->rnti, dlsch_harq->pdu,dlsch_harq->pdsch_start,dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0]);
      return;
    }

    start_meas(&eNB->dlsch_encoding_stats);

    eNB->te(eNB,
395
	  dlsch_harq->pdu,
396
	  dlsch_harq->pdsch_start,
397
	  dlsch,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
398 399
	  frame,
	  subframe,
400 401
	  &eNB->dlsch_rate_matching_stats,
	  &eNB->dlsch_turbo_encoding_stats,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
402
	  &eNB->dlsch_turbo_encoding_waiting_stats,
403
      &eNB->dlsch_turbo_encoding_main_stats,
404 405
      &eNB->dlsch_turbo_encoding_wakeup_stats0,
      &eNB->dlsch_turbo_encoding_wakeup_stats1,
406
	  &eNB->dlsch_interleaving_stats);
407
    stop_meas(&eNB->dlsch_encoding_stats);
408 409 410 411 412
  //////////////////////////////////////////////////*******************************************
  if(eNB->dlsch_encoding_stats.diff_now>500*3000 && opp_enabled == 1)
  {
    print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
  }
413
  // 36-211
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
    start_meas(&eNB->dlsch_scrambling_stats);
    dlsch_scrambling(fp,
        0,
        dlsch,
        harq_pid,
        get_G(fp,
          dlsch_harq->nb_rb,
          dlsch_harq->rb_alloc,
          dlsch_harq->Qm,
          dlsch_harq->Nl,
          dlsch_harq->pdsch_start,
          frame,subframe,
          0),
        0,
        frame,
        subframe<<1);
    stop_meas(&eNB->dlsch_scrambling_stats);

    start_meas(&eNB->dlsch_modulation_stats);

434
  
435
    dlsch_modulation(eNB,
436 437 438
		   eNB->common_vars.txdataF,
		   AMP,
		   subframe,
439
		   dlsch_harq->pdsch_start,
440 441 442
		   dlsch,
		   dlsch1);
  
443 444
    stop_meas(&eNB->dlsch_modulation_stats);
  }
445

446
  dlsch->active = 0;
447
  dlsch_harq->round++;
448 449

  LOG_D(PHY,"Generating DLSCH/PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
450
}
451 452


453

knopp's avatar
knopp committed
454

455
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
knopp's avatar
knopp committed
456
			   eNB_rxtx_proc_t *proc,
457
			   int do_meas)
458
{
459 460
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
461
  uint32_t i,aa;
462
  uint8_t harq_pid;
463
  int8_t UE_id=0;
464
  uint8_t num_pdcch_symbols=0;
465
  uint8_t num_dci=0;
466 467
  uint8_t ul_subframe;
  uint32_t ul_frame;
468
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
469
  LTE_UL_eNB_HARQ_t *ulsch_harq;
470

471
  int offset = eNB->CC_id;//proc == &eNB->proc.proc_rxtx[0] ? 0 : 1;
472

knopp's avatar
knopp committed
473

474
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)==SF_UL)) return;
475

476
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
477
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
478

479
  // clear the transmit data array for the current subframe
480 481 482
  for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {      
    memset(&eNB->common_vars.txdataF[aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
	   0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
knopp's avatar
knopp committed
483
  }
484
  
485

knopp's avatar
knopp committed
486

487 488
  if (nfapi_mode == 0 || nfapi_mode == 1) {
    if (is_pmch_subframe(frame,subframe,fp)) {
489
      pmch_procedures(eNB,proc);
490 491 492 493 494
    }
    else {
      // this is not a pmch subframe, so generate PSS/SSS/PBCH
      common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx);
    }
495
  }
496

knopp's avatar
knopp committed
497

knopp's avatar
knopp committed
498
  // clear existing ulsch dci allocations before applying info from MAC  (this is table
499
  ul_subframe = pdcch_alloc2ul_subframe(fp,subframe);
500
  ul_frame = pdcch_alloc2ul_frame(fp,frame,subframe);
501 502 503



knopp's avatar
knopp committed
504
  // clear previous allocation information for all UEs
505
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
506 507
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
knopp's avatar
knopp committed
508
  }
509

510
  /* save old HARQ information needed for PHICH generation */
511 512 513 514
  /* TODO: check the following test - in the meantime it is put back as it was before */
  //if ((ul_subframe < 10)&&
  //    (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here
  if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
      harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
      if (eNB->ulsch[i]) {
	ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid];
	
	/* Store first_rb and n_DMRS for correct PHICH generation below.
	 * For PHICH generation we need "old" values of last scheduling
	 * for this HARQ process. 'generate_eNB_dlsch_params' below will
	 * overwrite first_rb and n_DMRS and 'generate_phich_top', done
	 * after 'generate_eNB_dlsch_params', would use the "new" values
	 * instead of the "old" ones.
	 *
	 * This has been tested for FDD only, may be wrong for TDD.
	 *
	 * TODO: maybe we should restructure the code to be sure it
	 *       is done correctly. The main concern is if the code
	 *       changes and first_rb and n_DMRS are modified before
	 *       we reach here, then the PHICH processing will be wrong,
	 *       using wrong first_rb and n_DMRS values to compute
	 *       ngroup_PHICH and nseq_PHICH.
	 *
	 * TODO: check if that works with TDD.
	 */
	ulsch_harq->previous_first_rb = ulsch_harq->first_rb;
	ulsch_harq->previous_n_DMRS   = ulsch_harq->n_DMRS;
	
541 542 543 544
      }
    }
  }

545

546

547 548 549 550 551
  //  num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
  num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols;
  num_dci           = eNB->pdcch_vars[subframe&1].num_dci;
  //  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
  //        DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
Cedric Roux's avatar
Cedric Roux committed
552
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci);
553
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
554

555

556 557
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

558
  if (num_dci > 0)
Cedric Roux's avatar
Cedric Roux committed
559 560
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %"PRIu8") num_pdcch_symbols:%d\n",eNB->Mod_id,frame, subframe, num_dci, num_pdcch_symbols);

561 562 563 564 565 566 567 568 569 570 571 572 573 574
  //LOG_D(PHY,"Before generate_dci_top num_pdcch_symbols:%d num_dci:%d dci_alloc:dci_length:%d\n", num_pdcch_symbols, num_dci, eNB->pdcch_vars[subframe&1].dci_alloc[0].dci_length);

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);

  if (nfapi_mode == 0 || nfapi_mode == 1) {
    generate_dci_top(num_pdcch_symbols,
        num_dci,
        &eNB->pdcch_vars[subframe&1].dci_alloc[0],
        0,
        AMP,
        fp,
        eNB->common_vars.txdataF,
        subframe);
  }
575

576

gauthier's avatar
gauthier committed
577
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
578

579
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
knopp's avatar
knopp committed
580
  // Now scan UE specific DLSCH
581
  LTE_eNB_DLSCH_t *dlsch0,*dlsch1;
582
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
583
    {
584 585 586 587 588 589
      dlsch0 = eNB->dlsch[(uint8_t)UE_id][0]; 
      dlsch1 = eNB->dlsch[(uint8_t)UE_id][1]; 

      if ((dlsch0)&&
	  (dlsch0->rnti>0)&&
	  (dlsch0->active == 1)) {
590

591
	// get harq_pid
592
	harq_pid = dlsch0->harq_ids[subframe];
593
	AssertFatal(harq_pid>=0,"harq_pid is negative\n");
594 595 596 597 598 599 600 601

        if (harq_pid>=8)
        {
          LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x\n", harq_pid,UE_id,frame,subframe,dlsch0->rnti);
        }
        else
        {
          // generate pdsch
knopp's avatar
knopp committed
602

603 604 605 606 607 608 609 610
          pdsch_procedures(eNB,
              proc,
              harq_pid,
              dlsch0,
              dlsch1,
              &eNB->UE_stats[(uint32_t)UE_id],
              0);
        }
611 612


knopp's avatar
knopp committed
613
      }
614

gauthier's avatar
gauthier committed
615

616
      else if ((dlsch0)&&
617 618
          (dlsch0->rnti>0)&&
          (dlsch0->active == 0)) {
619

620 621
        // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
        dlsch0->subframe_tx[subframe]=0;
knopp's avatar
knopp committed
622
      }
knopp's avatar
knopp committed
623
    }
624
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
625

626 627


628
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,1);
629 630 631
  generate_phich_top(eNB,
		     proc,
		     AMP);
632
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,0);
633

634
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
635
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
636
  
637 638
}

639

640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
void srs_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;

  int i;

  if (is_srs_occasion_common(fp,frame,subframe)) { 
  
  // Do SRS processing 
  // check if there is SRS and we have to use shortened format
  // TODO: check for exceptions in transmission of SRS together with ACK/NACK
    for (i=0;i<NUMBER_OF_UE_MAX;i++) {

      if (eNB->soundingrs_ul_config_dedicated[i].active==1) {

      
	if (lte_srs_channel_estimation(fp,
				       &eNB->common_vars,
				       &eNB->srs_vars[i],
				       &eNB->soundingrs_ul_config_dedicated[i],
				       subframe,
				       0/*eNB_id*/)) {
	  LOG_E(PHY,"problem processing SRS\n");
	}
	eNB->soundingrs_ul_config_dedicated[i].active=0;
      }
    }
  }
}

672 673
void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) {
  
674
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
675 676 677 678 679 680 681 682
  nfapi_sr_indication_t       *sr_ind =         &eNB->UL_INFO.sr_ind;
  nfapi_sr_indication_body_t  *sr_ind_body =    &sr_ind->sr_indication_body;
  nfapi_sr_indication_pdu_t *pdu =   &sr_ind_body->sr_pdu_list[sr_ind_body->number_of_srs];

  sr_ind->sfn_sf = frame<<4|subframe;
  sr_ind->header.message_id = NFAPI_RX_SR_INDICATION;

  sr_ind_body->tl.tag = NFAPI_SR_INDICATION_BODY_TAG;
683 684 685

  pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
686
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
687 688
  pdu->rx_ue_information.rnti                         = rnti;

689 690 691
  int SNRtimes10 = dB_fixed_times10(stat) - 200;//(10*eNB->measurements.n0_power_dB[0]);


692 693
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;

694 695 696 697 698
  if      (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0;
  else if (SNRtimes10 >  635) pdu->ul_cqi_information.ul_cqi=255;
  else                        pdu->ul_cqi_information.ul_cqi=(640+SNRtimes10)/5;
  pdu->ul_cqi_information.channel = 0;

699
  sr_ind_body->number_of_srs++;
700 701 702 703
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}

void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
704
{
705
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
706
  uint8_t SR_payload = 0,pucch_b0b1[4][2]= {{0,0},{0,0},{0,0},{0,0}},harq_ack[4]={0,0,0,0};
707
  int32_t metric[4]={0,0,0,0},metric_SR=0,max_metric=0;
708 709
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
710 711 712 713
  int i;
  LTE_eNB_UCI *uci;
  uint16_t tdd_multiplexing_mask=0;
  int res;
714

715
  for (i=0;i<NUMBER_OF_UE_MAX;i++) {
716

717 718 719 720
    uci = &eNB->uci_vars[i];
    if ((uci->active == 1) &&
	(uci->frame == frame) &&
	(uci->subframe == subframe)) {
721

722
      LOG_D(PHY,"Frame %d, subframe %d: Running uci procedures (type %d) for %d \n",frame,subframe,uci->type,i);
723
      uci->active=0;
724

knopp's avatar
knopp committed
725 726 727
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
728 729
        eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
        break;
knopp's avatar
knopp committed
730
      case 15:
731 732
        eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
        break;
knopp's avatar
knopp committed
733
      case 25:
734 735
        eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
        break;
knopp's avatar
knopp committed
736
      case 50:
737 738 739
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
        break;
knopp's avatar
knopp committed
740
      case 75:
741 742 743
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
        break;
knopp's avatar
knopp committed
744
      case 100:
745 746 747
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
        break;
knopp's avatar
knopp committed
748
      default:
749 750
        LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
        break;
knopp's avatar
knopp committed
751
      }
752

753 754 755 756 757 758 759 760
      switch (uci->type) {
      case SR:
      case HARQ_SR:
		
	metric_SR = rx_pucch(eNB,
			      uci->pucch_fmt,
			      i,
			      uci->n_pucch_1_0_sr[0],
761
			      0, // n2_pucch
762
			      uci->srs_active, // shortened format
763 764 765 766
			      &SR_payload,
			      frame,
			      subframe,
			      PUCCH1_THRES);
knopp's avatar
knopp committed
767
	LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (SR n1pucch is %d)\n",
768
	      eNB->Mod_id,
769
	      uci->rnti,
770 771 772
	      frame,
	      subframe,
	      SR_payload,
773 774 775
	      uci->n_pucch_1_0_sr[0]);
	if (uci->type == SR) {
	  if (SR_payload == 1) {
776
	    fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
777
        continue;
778 779
	  }
	  else {
780
        continue;
781 782 783 784
	  }
	}
      case HARQ:
	if (fp->frame_type == FDD) {
785
	  LOG_D(PHY,"Frame %d Subframe %d Demodulating PUCCH (UCI %d) for ACK/NAK (uci->pucch_fmt %d,uci->type %d.uci->frame %d, uci->subframe %d): n1_pucch0 %d SR_payload %d\n",
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
		frame,subframe,i,
		uci->pucch_fmt,uci->type,
		uci->frame,uci->subframe,uci->n_pucch_1[0][0],
		SR_payload);
	  
	  metric[0] = rx_pucch(eNB,
			       uci->pucch_fmt,
			       i,
			       uci->n_pucch_1[0][0],
			       0, //n2_pucch
			       uci->srs_active, // shortened format
			       pucch_b0b1[0],
			       frame,
			       subframe,
			       PUCCH1a_THRES);
	  
	  
	  /* cancel SR detection if reception on n1_pucch0 is better than on SR PUCCH resource index, otherwise send it up to MAC */
	  if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0;
805
	  else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
 
	  if (uci->type==HARQ_SR && metric[0] <= metric_SR) {
	    /* when transmitting ACK/NACK on SR PUCCH resource index, SR payload is always 1 */
	    SR_payload = 1;
	    
	    metric[0]=rx_pucch(eNB,
			       uci->pucch_fmt,
			       i,
			       uci->n_pucch_1_0_sr[0],
			       0, //n2_pucch
			       uci->srs_active, // shortened format
			       pucch_b0b1[0],
			       frame,
			       subframe,
			       PUCCH1a_THRES);
	  }
	  
823

824
	  LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
825 826 827
		eNB->Mod_id,
		uci->rnti,
		frame,subframe,
828 829
		pucch_b0b1[0][0],metric[0]);

830
      uci->stat = metric[0]; 	  
831
	  fill_uci_harq_indication(eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff);
832

833 834
	}
	else { // frame_type == TDD
knopp's avatar
knopp committed
835

836

837 838
	  // if SR was detected, use the n1_pucch from SR
	  if (SR_payload==1) {
839
#ifdef DEBUG_PHY_PROC
840 841 842 843
	    LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d with SR\n",eNB->Mod_id,
		  eNB->dlsch[UE_id][0]->rnti,
		  frame,subframe,
		  n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
844
#endif
845 846 847 848 849 850 851 852 853 854 855 856
	    
	    metric[0] = rx_pucch(eNB,
				 pucch_format1b,
				 i,
				 uci->n_pucch_1_0_sr[0],
				 0, //n2_pucch
				 uci->srs_active, // shortened format
				 pucch_b0b1[0],
				 frame,
				 subframe,
				 PUCCH1a_THRES);
	  } else { //using assigned pucch resources
857
#ifdef DEBUG_PHY_PROC
858 859 860 861 862 863 864 865 866
	    LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK M=%d (%d,%d,%d,%d) format %d\n",eNB->Mod_id,
		  eNB->dlsch[UE_id][0]->rnti,
		  frame,subframe,
		  uci->num_pucch_resources,
		  uci->n_pucch_1[res][0],
		  uci->n_pucch_1[res][1],
		  uci->n_pucch_1[res][2],
		  uci->n_pucch_1[res][3],
		  uci->pucch_fmt);
867
#endif
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
	    for (res=0;res<uci->num_pucch_resources;res++)
	      metric[res] = rx_pucch(eNB,
				     uci->pucch_fmt,
				     i,
				     uci->n_pucch_1[res][0],
				     0, // n2_pucch
				     uci->srs_active, // shortened format
				     pucch_b0b1[res],
				     frame,
				     subframe,
				     PUCCH1a_THRES);
	  	  
	    

	  }
883

884
	  
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
	  if (SR_payload == 1) { // this implements Table 7.3.1 from 36.213
	    if (pucch_b0b1[0][0] == 4) { // there isn't a likely transmission
	      harq_ack[0] = 4; // DTX
	    }
	    else if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] == 1) { // 1/4/7 ACKs
	      harq_ack[0] = 1;
	    }
	    else if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] != 1) { // 2/5/8 ACKs
	      harq_ack[0] = 2;
	    }
	    else if (pucch_b0b1[1][0] != 1 && pucch_b0b1[1][1] == 1) { // 3/6/9 ACKs
	      harq_ack[0] = 3;
	    }
	    else if (pucch_b0b1[1][0] != 1 && pucch_b0b1[1][1] != 1) { // 0 ACKs, or at least one DL assignment missed
	      harq_ack[0] = 0;
	    }
901
        uci->stat = metric[0];
902 903
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode
	  } 
knopp's avatar
knopp committed
904
	  else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==2)){ // multiplexing + no SR, implement Table 10.1.3-5 (Rel14) for multiplexing with M=2
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
	    if (pucch_b0b1[0][0] == 4 ||
		pucch_b0b1[1][0] == 4) { // there isn't a likely transmission
	      harq_ack[0] = 4; // DTX
	      harq_ack[1] = 6; // NACK/DTX
	    } 
	    else {
	      if (metric[1]>metric[0]) {
		if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] != 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 1; // ACK
		  tdd_multiplexing_mask = 0x3;
		}
		else if (pucch_b0b1[1][0] != 1 && pucch_b0b1[1][1] == 1){
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 1; // ACK
		  tdd_multiplexing_mask = 0x2;
		}
		else {
		  harq_ack[0] = 4; // DTX
		  harq_ack[1] = 4; // DTX
		}
	      }
	      else {
		if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x1;
		}
		else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] != 1){
		  harq_ack[0] = 2; // NACK
		  harq_ack[1] = 6; // NACK/DTX
		}
		else {
		  harq_ack[0] = 4; // DTX
		  harq_ack[1] = 4; // DTX
		}
	      }
	    }
943
        uci->stat = max(metric[0],metric[1]);
944
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
945
	  } //else if ((uci->tdd_bundling == 0) && (res==2))
knopp's avatar
knopp committed
946
	  else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==3)){ // multiplexing + no SR, implement Table 10.1.3-6 (Rel14) for multiplexing with M=3
947 948 949 950 951 952 953
	    
	    if (harq_ack[0] == 4 ||
		harq_ack[1] == 4 ||
		harq_ack[2] == 4) { // there isn't a likely transmission
	      harq_ack[0] = 4; // DTX
	      harq_ack[1] = 6; // NACK/DTX
	      harq_ack[2] = 6; // NACK/DTX
954
              max_metric = 0;
955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
	    } 
	    else {
	      
	      max_metric = max(metric[0],max(metric[1],metric[2]));
	      
	      if (metric[0]==max_metric) {
		if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x1;
		}
		else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] != 1){
		  harq_ack[0] = 2; // NACK
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 6; // NACK/DTX
		}
		else {
		  harq_ack[0] = 4; // DTX
		  harq_ack[1] = 4; // DTX
		  harq_ack[2] = 4; // DTX
		}
	      } // if (metric[0]==max_metric) {
	      else if (metric[1]==max_metric) {
	      
	        if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] != 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x3;
		}
		else if (pucch_b0b1[1][0] != 1 && pucch_b0b1[1][1] == 1 ) {
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x2;
		}
		else {
		  harq_ack[0] = 4; // DTX
		  harq_ack[1] = 4; // DTX
		  harq_ack[2] = 4; // DTX
		}
	      } // if (metric[1]==max_metric) {
	      else {
  	        if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 1; // ACK
		  tdd_multiplexing_mask = 0x7;
		}
		else if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] != 1 ) {
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 1; // ACK
		  tdd_multiplexing_mask = 0x5;
		}
		else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] == 1 ) {
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 1; // ACK
		  tdd_multiplexing_mask = 0x6;
		}
		else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] != 1 ) {
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 1; // ACK
		  tdd_multiplexing_mask = 0x4;
		}
	      }
1024
            uci->stat = max_metric;
1025
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
1026
	    }
1027
	  } //else if ((uci->tdd_bundling == 0) && (res==3)) 
knopp's avatar
knopp committed
1028
	  else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==4)){ // multiplexing + no SR, implement Table 10.1.3-7 (Rel14) for multiplexing with M=4
1029 1030 1031 1032 1033 1034 1035 1036
	    if (pucch_b0b1[0][0] == 4 ||
		pucch_b0b1[1][0] == 4 ||
		pucch_b0b1[2][0] == 4 ||
		pucch_b0b1[3][0] == 4) { // there isn't a likely transmission
	      harq_ack[0] = 4; // DTX
	      harq_ack[1] = 6; // NACK/DTX
	      harq_ack[2] = 6; // NACK/DTX
	      harq_ack[3] = 6; // NACK/DTX
1037
              max_metric = 0;
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
	    } else {

	      max_metric = max(metric[0],max(metric[1],max(metric[2],metric[3])));
	      
	      if (metric[0]==max_metric) {
		if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] != 1){
		  harq_ack[0] = 2; // NACK
		  harq_ack[1] = 4; // DTX
		  harq_ack[2] = 4; // DTX
		  harq_ack[3] = 4; // DTX
		}
		else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 6; // NACK/DTX
		  harq_ack[3] = 1; // ACK
		  tdd_multiplexing_mask = 0x9;
		}
		else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 6; // NACK/DTX
		  harq_ack[3] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x1;
		}
		else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] != 1){
		  harq_ack[0] = 2; // NACK
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 6; // NACK/DTX
		  harq_ack[3] = 6; // NACK/DTX
		}
		
	      } 
	      else if (metric[1]==max_metric) {
		if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 1; // ACK
		  harq_ack[3] = 1; // ACK
		  tdd_multiplexing_mask = 0xF;
		}
		else if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] != 1 ) {
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 6; // NACK/DTX
		  harq_ack[3] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x3;
		}
		else if (pucch_b0b1[1][0] != 1 && pucch_b0b1[1][1] != 1 ) {
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 1; // ACK
		  harq_ack[3] = 1; // ACK
		  tdd_multiplexing_mask = 0xE;
		}
		else if (pucch_b0b1[1][0] != 1 && pucch_b0b1[1][1] == 1 ) {
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 6; // NACK/DTX
		  harq_ack[3] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x2;
		}
	      } 
	      else if (metric[2]==max_metric) {
		if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 1; // ACK
		  harq_ack[3] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x7;
		}
		else if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] != 1 ) {
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 1; // ACK
		  harq_ack[3] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x5;
		}
		else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] == 1 ) {
		  harq_ack[0] = 4; // NACK/DTX
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 1; // ACK
		  harq_ack[3] = 4; // NACK/DTX
		  tdd_multiplexing_mask = 0x6;
		}
		else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] != 1 ) {
		  harq_ack[0] = 4; // NACK/DTX
		  harq_ack[1] = 4; // NACK/DTX
		  harq_ack[2] = 1; // ACK
		  harq_ack[3] = 4; // NACK/DTX
		  tdd_multiplexing_mask = 0x4;
		}
	      } 
	      else { // max_metric[3]=max_metric
		if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 1; // ACK
		  harq_ack[3] = 1; // ACK
		  tdd_multiplexing_mask = 0xD;
		}
		else if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] != 1 ) {
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 1; // ACK
		  harq_ack[2] = 6; // NACK/DTX
		  harq_ack[3] = 1; // ACK
		  tdd_multiplexing_mask = 0xA;
		}
		else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] == 1 ) {
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 1; // ACK
		  harq_ack[3] = 1; // ACK
		  tdd_multiplexing_mask = 0xC;
		}
		else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] != 1 ) {
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 6; // NACK/DTX
		  harq_ack[2] = 6; // NACK/DTX
		  harq_ack[3] = 1; // ACK
		  tdd_multiplexing_mask = 0x8;
		}
	      }
	    }
1162
        uci->stat = max_metric;
1163
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
1164
	  } // else if ((uci->tdd_bundling == 0) && (res==4))
1165 1166 1167
	  else { // bundling
	    harq_ack[0] = pucch_b0b1[0][0];
	    harq_ack[1] = pucch_b0b1[0][1];
1168
        uci->stat = metric[0];
1169 1170
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode
	  }
1171
	  
1172
#ifdef DEBUG_PHY_PROC
knopp's avatar
knopp committed
1173
	  LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, (%d,%d)\n",eNB->Mod_id,
1174 1175
		eNB->dlsch[UE_id][0]->rnti,
		frame,subframe,
knopp's avatar
knopp committed
1176
		metric0,metric1,pucch_b0b1[0],pucch_b0b1[1]);
1177
#endif
1178 1179 1180 1181 1182
	}
	break;
      default:
	AssertFatal(1==0,"Unsupported UCI type %d\n",uci->type);
	break;
1183
      }
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196
    
      if (SR_payload == 1) {
	LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id,
	      uci->rnti,frame,subframe);
	
	if (eNB->first_sr[i] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
	  eNB->first_sr[i] = 0;
	  eNB->dlsch[i][0]->harq_processes[0]->round=0;
	  eNB->dlsch[i][0]->harq_processes[0]->status=SCH_IDLE;
	  LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n",
		eNB->Mod_id,
		eNB->ulsch[i]->rnti,frame,subframe);
	}
1197 1198 1199
      }
    }
  }
1200
}
1201

Cedric Roux's avatar
Cedric Roux committed
1202 1203
void pusch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
{
knopp's avatar
knopp committed
1204 1205
  uint32_t ret=0,i;
  uint32_t harq_pid;
1206 1207 1208 1209
  uint8_t nPRS;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  LTE_eNB_ULSCH_t *ulsch;
  LTE_UL_eNB_HARQ_t *ulsch_harq;
1210

1211 1212
  const int subframe = proc->subframe_rx;
  const int frame    = proc->frame_rx;
1213
  
1214 1215
  if (fp->frame_type == FDD) harq_pid = ((10*frame) + subframe)&7;
  else                       harq_pid = subframe%10;
1216

1217 1218 1219
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    ulsch = eNB->ulsch[i];
    ulsch_harq = ulsch->harq_processes[harq_pid];
1220 1221 1222 1223
    if (ulsch->rnti>0) LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n",
			     i, harq_pid, frame,subframe,i,ulsch->rnti,
                             ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled);
    
1224 1225 1226
    if ((ulsch) &&
        (ulsch->rnti>0) &&
        (ulsch_harq->status == ACTIVE) &&
1227 1228
	    (ulsch_harq->frame == frame) &&
	    (ulsch_harq->subframe == subframe) &&
1229
        (ulsch_harq->handled == 0)) {
1230
      
1231
      // UE has ULSCH scheduling
1232 1233
      for (int rb=0;
           rb<=ulsch_harq->nb_rb;
1234 1235 1236
	   rb++) {
	int rb2 = rb+ulsch_harq->first_rb;
	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
1237
      }
1238

Cedric Roux's avatar
Cedric Roux committed
1239
      LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", eNB->Mod_id, frame, subframe, i);
1240

1241
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
1242

Cedric Roux's avatar
Cedric Roux committed
1243
      ulsch->cyclicShift = (ulsch_harq->n_DMRS2 +
1244 1245
          fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
          nPRS)%12;
1246

knopp's avatar
knopp committed
1247
      LOG_D(PHY,
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
          "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, Qm %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, ), O_ACK %d, beta_cqi %d \n",
          eNB->Mod_id,harq_pid,frame,subframe,
          ulsch_harq->dci_alloc,
          ulsch_harq->rar_alloc,
          ulsch_harq->round,
          ulsch_harq->first_rb,
          ulsch_harq->nb_rb,
          ulsch_harq->Qm,
          ulsch_harq->TBS,
          ulsch_harq->rvidx,
          ulsch->cyclicShift,
          ulsch_harq->n_DMRS2,
          fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
          ulsch_harq->O_ACK,
          ulsch->beta_offset_cqi_times8);

        start_meas(&eNB->ulsch_demodulation_stats);
1265

1266
	rx_ulsch(eNB,proc, i);
1267

1268
        stop_meas(&eNB->ulsch_demodulation_stats);
1269

1270
        start_meas(&eNB->ulsch_decoding_stats);
1271

1272 1273 1274 1275 1276
        ret = ulsch_decoding(eNB,proc,
            i,
            0, // control_only_flag
            ulsch_harq->V_UL_DAI,
            ulsch_harq->nb_rb>20 ? 1 : 0);
Sandeep Kumar's avatar
Sandeep Kumar committed
1277

1278
        stop_meas(&eNB->ulsch_decoding_stats);
1279

1280
        LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n",
1281 1282 1283 1284 1285 1286 1287 1288 1289
            eNB->Mod_id,harq_pid,
            frame,subframe,
            ulsch->rnti,
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
            20,//eNB->measurements.n0_power_dB[0],
            20,//eNB->measurements.n0_power_dB[1],
            ulsch_harq->o_ACK[0],
            ulsch_harq->o_ACK[1],
1290 1291 1292 1293
            ret,
            ulsch_harq->cqi_crc_status,
            ulsch_harq->O_ACK,
            eNB->ulsch_decoding_stats.diff_now, eNB->ulsch_decoding_stats.max);
1294

1295 1296
        //compute the expected ULSCH RX power (for the stats)
        ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
1297

1298
        if (ulsch_harq->cqi_crc_status == 1) {
1299
#ifdef DEBUG_PHY_PROC
1300 1301
          //if (((frame%10) == 0) || (frame < 50))
          print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL);
1302 1303
#endif

1304 1305 1306
	fill_ulsch_cqi_indication(eNB,frame,subframe,
				  ulsch_harq,
				  ulsch->rnti);
1307
      }
1308
      
1309
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
Cedric Roux's avatar
Cedric Roux committed
1310
        T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti),
1311 1312
          T_INT(harq_pid));

1313 1314
	fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC
	fill_rx_indication(eNB,i,frame,subframe);  // indicate SDU to MAC
1315

1316 1317 1318
	LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n",
	      eNB->Mod_id,harq_pid,
	      frame,subframe, i,
1319
	      ulsch_harq->round,
1320 1321 1322
	      ulsch->Mlimit,
	      ulsch_harq->o_ACK[0],
	      ulsch_harq->o_ACK[1]);
1323

Cedric Roux's avatar
Cedric Roux committed
1324
        if (ulsch_harq->round >= 3)  {
1325 1326 1327 1328
           ulsch_harq->status  = SCH_IDLE;
           ulsch_harq->handled = 0;
           ulsch->harq_mask   &= ~(1 << harq_pid);
           ulsch_harq->round   = 0;
1329
	  }
1330
#if defined(MESSAGE_CHART_GENERATOR_PHY)
Cedric Roux's avatar
Cedric Roux committed
1331
        MSC_LOG_RX_DISCARDED_MESSAGE(
1332 1333 1334 1335 1336 1337 1338
            MSC_PHY_ENB,MSC_PHY_UE,
            NULL,0,
            "%05u:%02u ULSCH received rnti %x harq id %u round %d",
            frame,subframe,
            ulsch->rnti,harq_pid,
            ulsch_harq->round-1
            );
1339
#endif
Cedric Roux's avatar
Cedric Roux committed
1340 1341 1342 1343 1344 1345 1346

        /* Mark the HARQ process to release it later if max transmission reached
         * (see below).
         * MAC does not send the max transmission count, we have to deal with it
         * locally in PHY.
         */
        ulsch_harq->handled = 1;
1347 1348
      }  // ulsch in error
      else {
1349 1350
	fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC
	fill_rx_indication(eNB,i,frame,subframe);  // indicate SDU to MAC
Cedric Roux's avatar
Cedric Roux committed
1351 1352 1353

        ulsch_harq->status = SCH_IDLE;
        ulsch->harq_mask   &= ~(1 << harq_pid);
1354

Cedric Roux's avatar
Cedric Roux committed
1355
        T(T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti),
1356 1357 1358
          T_INT(harq_pid));

#if defined(MESSAGE_CHART_GENERATOR_PHY)
1359 1360 1361 1362 1363 1364 1365
          MSC_LOG_RX_MESSAGE(
              MSC_PHY_ENB,MSC_PHY_UE,
              NULL,0,
              "%05u:%02u ULSCH received rnti %x harq id %u",
              frame,subframe,
              ulsch->rnti,harq_pid
              );
1366 1367 1368 1369
#endif

#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
Cedric Roux's avatar