phy_procedures_lte_eNb.c 68.6 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
Cedric Roux's avatar
Cedric Roux committed
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
33
34
35
36
 * \note
 * \warning
 */

#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
37
#include "nfapi_interface.h"
38
#include "fapi_l1.h"
39
40
41
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

42
43
#include "T.h"

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

47
48
#include <time.h>

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

53
54
extern uint8_t nfapi_mode;
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind);
55

knopp's avatar
   
knopp committed
56

57

58
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,relaying_type_t r_type) {
59
60


Cedric Roux's avatar
Cedric Roux committed
61
#if defined(Rel10) || defined(Rel14)
knopp's avatar
knopp committed
62
  MCH_PDU *mch_pduP=NULL;
63
  MCH_PDU  mch_pdu;
64
  //  uint8_t sync_area=255;
65
#endif
66

67
  int subframe = proc->subframe_tx;
68

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

71
72
73
74
75
76
  // This is DL-Cell spec pilots in Control region
  generate_pilots_slot(eNB,
		       eNB->common_vars.txdataF,
		       AMP,
		       subframe<<1,1);

77
  
Cedric Roux's avatar
Cedric Roux committed
78
#if defined(Rel10) || defined(Rel14)
79
80
  // 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
81
  /*
82
83
  mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id,
				    eNB->CC_id,
84
				    proc->frame_tx,
85
				    subframe);
86
  */
87
88
89
  switch (r_type) {
  case no_relay:
    if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0
knopp's avatar
knopp committed
90
      LOG_D(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n",
91
92
	    eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs,
	    eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
93
94
    else {
      LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n",
95
	    eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->sync_area,
96
97
	    (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment");
      mch_pduP = NULL;
gauthier's avatar
For RAL    
gauthier committed
98
    }
99
    
knopp's avatar
   
knopp committed
100
    break;
101
102
103
    
  case multicast_relay:
    if ((mch_pduP->Pdu_size > 0) && ((mch_pduP->mcch_active == 1) || mch_pduP->msi_active==1)) {
knopp's avatar
knopp committed
104
      LOG_D(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Got the MCH PDU for MBSFN  sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n",
105
106
107
108
109
110
111
112
113
	    rn->Mod_id,rn->frame, subframe,
	    mch_pduP->sync_area,mch_pduP->mcs,mch_pduP->Pdu_size);
    } else if (rn->mch_avtive[subframe%5] == 1) { // SF2 -> SF7, SF3 -> SF8
      mch_pduP= &mch_pdu;
      memcpy(&mch_pduP->payload, // could be a simple copy
	     rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->b,
	     rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3);
      mch_pduP->Pdu_size = (uint16_t) (rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3);
      mch_pduP->mcs = rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->mcs;
knopp's avatar
knopp committed
114
      LOG_D(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Forward the MCH PDU for MBSFN received on SF %d sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n",
115
116
	    rn->Mod_id,rn->frame, subframe,subframe%5,
	    rn->sync_area[subframe%5],mch_pduP->mcs,mch_pduP->Pdu_size);
knopp's avatar
   
knopp committed
117
    } else {
118
      mch_pduP=NULL;
knopp's avatar
   
knopp committed
119
    }
120
121
    
    rn->mch_avtive[subframe]=0;
knopp's avatar
   
knopp committed
122
    break;
123
    
124
  default:
125
    LOG_W(PHY,"[eNB %"PRIu8"] Frame %d subframe %d: unknown relaying type %d \n",
126
	  eNB->Mod_id,proc->frame_tx,subframe,r_type);
127
128
129
130
131
    mch_pduP=NULL;
    break;
  }// switch
  
  if (mch_pduP) {
132
    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0);
133
    // Generate PMCH
134
    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload);
135
  } else {
136
    LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe);
knopp's avatar
   
knopp committed
137
  }
138
  
139
#endif
140
}
141

142
void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
143

144
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
145
  int **txdataF = eNB->common_vars.txdataF;
146
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
147

148
  //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?"); 
149

150
  // generate Cell-Specific Reference Signals for both slots
151
152
153
154
155
156
157
  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)
158
159
160
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
161
162
163
164
			 (subframe<<1)+1,0);
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0);
      
165

166
  // First half of PSS/SSS (FDD, slot 0)
knopp's avatar
   
knopp committed
167
  if (subframe == 0) {
168
    if (fp->frame_type == FDD) {
169
170
171
172
173
174
175
176
177
178
179
      generate_pss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   0);
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 5 : 4,
		   0);
      
180
    }
181
    
182
183


184
185
186
      
    /// First half of SSS (TDD, slot 1)
    
187
    if (fp->frame_type == TDD) {
188
189
190
191
192
193
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   1);
    }
194

195
196
    // generate PBCH (Physical Broadcast CHannel) info

197
    /// generate PBCH
198
    if ((frame&3)==0) {
199
200
      //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n");
      if (eNB->pbch_configured!=1) return;
201
      eNB->pbch_configured=0;
202
    }
203
204
205
206
207
208
209
    generate_pbch(&eNB->pbch,
		  txdataF,
		  AMP,
		  fp,
		  pbch_pdu,
		  frame&3);
  
210
  }
211
  else if ((subframe == 1) &&
212
	   (fp->frame_type == TDD)){
213
214
215
216
217
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
218
  }
219
220
221
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
222
	   (fp->frame_type == FDD)) {
223
224
225
226
227
228
229
230
231
232
    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);
233

234
  }
235

236
237
  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
238
	   (fp->frame_type == TDD)) {
239
240
241
242
243
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
knopp's avatar
   
knopp committed
244
  }
knopp's avatar
   
knopp committed
245

246
247
  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
248
	   (fp->frame_type == TDD)) { 
249
250
251
252
253
254
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }
knopp's avatar
   
knopp committed
255

256
}
knopp's avatar
   
knopp committed
257

258
259


260
261
262
263
264
265
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,
266
		      int ra_flag) {
267

268
269
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
270
271
  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
  int input_buffer_length = dlsch_harq->TBS/8;
272
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
273

274
  if (dlsch->rnti == 0x02) {//frame < 200) {
275

276
    LOG_D(PHY,
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
	  "[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);
  }    
297
#if defined(MESSAGE_CHART_GENERATOR_PHY)
298
299
300
  MSC_LOG_TX_MESSAGE(
		     MSC_PHY_ENB,MSC_PHY_UE,
		     NULL,0,
301
		     "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", TBS %"PRIu16", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
302
303
304
305
306
		     frame, subframe,
		     input_buffer_length,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
307
			   dlsch_harq->Qm,
308
			   dlsch_harq->Nl,
309
			   dlsch_harq->pdsch_start,
310
311
312
			   frame,
			   subframe,
			   dlsch_harq->mimo_mode==TM7?7:0),
313
		     dlsch_harq->nb_rb,
314
		     dlsch_harq->TBS,
315
316
317
318
		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
		     dlsch_harq->rvidx,
		     dlsch_harq->round);
#endif
319
320
  
  
321
  if (ue_stats) ue_stats->dlsch_sliding_cnt++;
322
  
323
324
325
  if (dlsch_harq->round == 0) {
    if (ue_stats)
      ue_stats->dlsch_trials[harq_pid][0]++;
326
327
328
329
330
331
332
333
  } 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
  }
334
335


336
337
  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);
338
  // 36-212 
339
340
341
342
343
344
  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;
    }
345

346
347
348
    start_meas(&eNB->dlsch_encoding_stats);

    eNB->te(eNB,
349
	  dlsch_harq->pdu,
350
	  dlsch_harq->pdsch_start,
351
	  dlsch,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
352
353
	  frame,
	  subframe,
354
355
	  &eNB->dlsch_rate_matching_stats,
	  &eNB->dlsch_turbo_encoding_stats,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
356
	  &eNB->dlsch_turbo_encoding_waiting_stats,
357
      &eNB->dlsch_turbo_encoding_main_stats,
358
359
      &eNB->dlsch_turbo_encoding_wakeup_stats0,
      &eNB->dlsch_turbo_encoding_wakeup_stats1,
360
	  &eNB->dlsch_interleaving_stats);
361
    stop_meas(&eNB->dlsch_encoding_stats);
362
363
364
365
366
  //////////////////////////////////////////////////*******************************************
  if(eNB->dlsch_encoding_stats.diff_now>500*3000 && opp_enabled == 1)
  {
    print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
  }
367
  // 36-211
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
    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);

388
  
389
    dlsch_modulation(eNB,
390
391
392
		   eNB->common_vars.txdataF,
		   AMP,
		   subframe,
393
		   dlsch_harq->pdsch_start,
394
395
396
		   dlsch,
		   dlsch1);
  
397
398
    stop_meas(&eNB->dlsch_modulation_stats);
  }
399

400
  dlsch->active = 0;
401
  dlsch_harq->round++;
402
//printf("  dlsch_harq ++ %p %d.%d harq %d rnti %d\n", dlsch_harq, frame, subframe, harq_pid, dlsch->rnti);
403
404

  LOG_D(PHY,"Generating DLSCH/PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
405
}
406
407


408

knopp's avatar
knopp committed
409

410
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
knopp's avatar
knopp committed
411
			   eNB_rxtx_proc_t *proc,
412
                           relaying_type_t r_type,
413
414
			   PHY_VARS_RN *rn,
			   int do_meas)
415
416
{
  UNUSED(rn);
417
418
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
419
  uint32_t i,aa;
420
  uint8_t harq_pid;
421
  int8_t UE_id=0;
422
  uint8_t num_pdcch_symbols=0;
423
  uint8_t num_dci=0;
424
425
  uint8_t ul_subframe;
  uint32_t ul_frame;
426
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
427
  LTE_UL_eNB_HARQ_t *ulsch_harq;
428

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

knopp's avatar
knopp committed
431

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

Raymond Knopp's avatar
Raymond Knopp committed
434
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
435
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
436

437
  // clear the transmit data array for the current subframe
438
439
440
  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
441
  }
442
  
443

knopp's avatar
knopp committed
444

445
446
447
448
449
450
451
452
  if (nfapi_mode == 0 || nfapi_mode == 1) {
    if (is_pmch_subframe(frame,subframe,fp)) {
      pmch_procedures(eNB,proc,rn,r_type);
    }
    else {
      // this is not a pmch subframe, so generate PSS/SSS/PBCH
      common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx);
    }
453
  }
454

knopp's avatar
knopp committed
455

knopp's avatar
   
knopp committed
456
  // clear existing ulsch dci allocations before applying info from MAC  (this is table
457
  ul_subframe = pdcch_alloc2ul_subframe(fp,subframe);
458
  ul_frame = pdcch_alloc2ul_frame(fp,frame,subframe);
459
460
461



knopp's avatar
   
knopp committed
462
  // clear previous allocation information for all UEs
463
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
464
465
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
knopp's avatar
   
knopp committed
466
  }
467

Cedric Roux's avatar
Cedric Roux committed
468
  /* save old HARQ information needed for PHICH generation */
469
470
471
472
  /* 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
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
    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;
	
Cedric Roux's avatar
Cedric Roux committed
499
500
501
502
      }
    }
  }

503

504

505
506
507
508
509
  //  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
510
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci);
511
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
512

513

514
515
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

516
  if (num_dci > 0)
Cedric Roux's avatar
Cedric Roux committed
517
518
    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);

519
520
521
  //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);
522
//printf("//////////************before generate_dci_top UL %d.%d TX %d.%d \n", ul_frame, ul_subframe, frame, subframe);
523
524
525
526
527
528
529
530
531
532
  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);
  }
533

534

gauthier's avatar
gauthier committed
535
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
536

537
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
knopp's avatar
   
knopp committed
538
  // Now scan UE specific DLSCH
539
  LTE_eNB_DLSCH_t *dlsch0,*dlsch1;
540
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
541
    {
542
543
544
545
546
547
      dlsch0 = eNB->dlsch[(uint8_t)UE_id][0]; 
      dlsch1 = eNB->dlsch[(uint8_t)UE_id][1]; 

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

549
	// get harq_pid
550
	harq_pid = dlsch0->harq_ids[subframe];
551
	AssertFatal(harq_pid>=0,"harq_pid is negative\n");
552
553
554
555
556
557
558
559

        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
560
//printf("%d.%d pdsch_procedures ue rnti %d\n", frame, subframe, dlsch0->rnti);///////////////////////////////////**********************
561
562
563
564
565
566
567
568
          pdsch_procedures(eNB,
              proc,
              harq_pid,
              dlsch0,
              dlsch1,
              &eNB->UE_stats[(uint32_t)UE_id],
              0);
        }
569
570


knopp's avatar
   
knopp committed
571
      }
572

gauthier's avatar
gauthier committed
573

574
      else if ((dlsch0)&&
575
576
          (dlsch0->rnti>0)&&
          (dlsch0->active == 0)) {
577

578
579
        // 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
580
      }
knopp's avatar
   
knopp committed
581
    }
582
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
583

584
585


586
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,1);
587
588
589
  generate_phich_top(eNB,
		     proc,
		     AMP);
590
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,0);
591

Raymond Knopp's avatar
Raymond Knopp committed
592
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
593
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
594
  
595
596
}

597

598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
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;
      }
    }
  }
}

630
631
void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) {
  
632
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
633
634
635
636
637
638
639
640
  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;
641
642
643

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

647
648
649
  int SNRtimes10 = dB_fixed_times10(stat) - 200;//(10*eNB->measurements.n0_power_dB[0]);


650
651
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;

652
653
654
655
656
  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;

657
  sr_ind_body->number_of_srs++;
658
659
660
661
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}

void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
Cedric Roux's avatar
Cedric Roux committed
662
{
663
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
664
  uint8_t SR_payload = 0,pucch_b0b1[4][2]= {{0,0},{0,0},{0,0},{0,0}},harq_ack[4]={0,0,0,0};
665
  int32_t metric[4]={0,0,0,0},metric_SR=0,max_metric=0;
666
667
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
668
669
670
671
  int i;
  LTE_eNB_UCI *uci;
  uint16_t tdd_multiplexing_mask=0;
  int res;
672

673
  for (i=0;i<NUMBER_OF_UE_MAX;i++) {
Cedric Roux's avatar
Cedric Roux committed
674

675
676
677
678
    uci = &eNB->uci_vars[i];
    if ((uci->active == 1) &&
	(uci->frame == frame) &&
	(uci->subframe == subframe)) {
679

680
      LOG_D(PHY,"Frame %d, subframe %d: Running uci procedures (type %d) for %d \n",frame,subframe,uci->type,i);
681
      uci->active=0;
Cedric Roux's avatar
Cedric Roux committed
682

knopp's avatar
knopp committed
683
684
685
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
Cedric Roux's avatar
Cedric Roux committed
686
687
        eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
        break;
knopp's avatar
knopp committed
688
      case 15:
Cedric Roux's avatar
Cedric Roux committed
689
690
        eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
        break;
knopp's avatar
knopp committed
691
      case 25:
Cedric Roux's avatar
Cedric Roux committed
692
693
        eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
        break;
knopp's avatar
knopp committed
694
      case 50:
Cedric Roux's avatar
Cedric Roux committed
695
696
697
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
        break;
knopp's avatar
knopp committed
698
      case 75:
Cedric Roux's avatar
Cedric Roux committed
699
700
701
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
        break;
knopp's avatar
knopp committed
702
      case 100:
Cedric Roux's avatar
Cedric Roux committed
703
704
705
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
        break;
knopp's avatar
knopp committed
706
      default:
Cedric Roux's avatar
Cedric Roux committed
707
708
        LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
        break;
knopp's avatar
knopp committed
709
      }
710

711
712
713
714
715
716
717
718
      switch (uci->type) {
      case SR:
      case HARQ_SR:
		
	metric_SR = rx_pucch(eNB,
			      uci->pucch_fmt,
			      i,
			      uci->n_pucch_1_0_sr[0],
719
			      0, // n2_pucch
720
			      uci->srs_active, // shortened format
721
722
723
724
			      &SR_payload,
			      frame,
			      subframe,
			      PUCCH1_THRES);
knopp's avatar
knopp committed
725
	LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (SR n1pucch is %d)\n",
726
	      eNB->Mod_id,
727
	      uci->rnti,
728
729
730
	      frame,
	      subframe,
	      SR_payload,
731
732
733
	      uci->n_pucch_1_0_sr[0]);
	if (uci->type == SR) {
	  if (SR_payload == 1) {
734
	    fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
735
        continue;
736
737
	  }
	  else {
738
        continue;
739
740
741
742
	  }
	}
      case HARQ:
	if (fp->frame_type == FDD) {
743
	  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",
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
		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;
763
	  else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
 
	  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);
	  }
	  
781

782
	  LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
783
784
785
		eNB->Mod_id,
		uci->rnti,
		frame,subframe,
786
787
		pucch_b0b1[0][0],metric[0]);

788
      uci->stat = metric[0]; 	  
789
	  fill_uci_harq_indication(eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff);
790

791
792
	}
	else { // frame_type == TDD
knopp's avatar
knopp committed
793

794

795
796
	  // if SR was detected, use the n1_pucch from SR
	  if (SR_payload==1) {
797
#ifdef DEBUG_PHY_PROC
798
799
800
801
	    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);
802
#endif
803
804
805
806
807
808
809
810
811
812
813
814
	    
	    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
815
#ifdef DEBUG_PHY_PROC
816
817
818
819
820
821
822
823
824
	    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);
825
#endif
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
	    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);
	  	  
	    

	  }
841

842
	  
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
	  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;
	    }
859
        uci->stat = metric[0];
860
861
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode
	  } 
knopp's avatar
knopp committed
862
	  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
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
	    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
		}
	      }
	    }
901
        uci->stat = max(metric[0],metric[1]);
902
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
knopp's avatar
knopp committed
903
	  } //else if ((uci->tdd_bundling == 0) && (res==2))
knopp's avatar
knopp committed
904
	  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
905
906
907
908
909
910
911
	    
	    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
Cedric Roux's avatar
Cedric Roux committed
912
              max_metric = 0;
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
943
944
945
946
947
948
949
950
951
952
953
954
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
	    } 
	    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;
		}
	      }
982
            uci->stat = max_metric;
983
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
984
	    }
knopp's avatar
knopp committed
985
	  } //else if ((uci->tdd_bundling == 0) && (res==3)) 
knopp's avatar
knopp committed
986
	  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
987
988
989
990
991
992
993
994
	    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
Cedric Roux's avatar
Cedric Roux committed
995
              max_metric = 0;
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
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
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
	    } 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