phy_procedures_lte_eNb.c 73.4 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
 * \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
For RAL    
gauthier committed
51
#   include "intertask_interface.h"
52
53
#endif

54
extern uint8_t nfapi_mode;
55
56
57



58
int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t UE_id,uint8_t harq_pid, uint8_t bw_factor)
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
{

  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
  return(subframe_select(&RC.eNB[Mod_id][CC_id]->frame_parms,subframe));

}
137

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


141
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
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
  
157
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
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
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
198
199
200
201
202
203
204

   if(subframe_select(fp,subframe) == SF_S)
       generate_pilots_slot(eNB,
                    txdataF,
                    AMP,
                    subframe<<1,1);
   else
205
206
207
208
  generate_pilots_slot(eNB,
		       txdataF,
		       AMP,
		       subframe<<1,0);
209
210
211

 // check that 2nd slot is for DL

212
213
  // check that 2nd slot is for DL
  if (subframe_select(fp,subframe) == SF_DL)
214
215
216
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
217
218
219
220
			 (subframe<<1)+1,0);
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0);
      
221

222
  // First half of PSS/SSS (FDD, slot 0)
knopp's avatar
   
knopp committed
223
  if (subframe == 0) {
224
    if (fp->frame_type == FDD) {
225
226
227
228
229
230
231
232
233
234
235
      generate_pss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   0);
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 5 : 4,
		   0);
      
236
    }
237
    
238
239


240
241
242
      
    /// First half of SSS (TDD, slot 1)
    
243
    if (fp->frame_type == TDD) {
244
245
246
247
248
249
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   1);
    }
250

251
252
    // generate PBCH (Physical Broadcast CHannel) info

253
    /// generate PBCH
254
    if ((frame&3)==0) {
255
256
      //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n");
      if (eNB->pbch_configured!=1) return;
257
      eNB->pbch_configured=0;
258
    }
259
260
261
262
263
264
265
    generate_pbch(&eNB->pbch,
		  txdataF,
		  AMP,
		  fp,
		  pbch_pdu,
		  frame&3);
  
266
  }
267
  else if ((subframe == 1) &&
268
	   (fp->frame_type == TDD)){
269
270
271
272
273
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
274
  }
275
276
277
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
278
	   (fp->frame_type == FDD)) {
279
280
281
282
283
284
285
286
287
288
    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);
289

290
  }
291

292
293
  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
294
	   (fp->frame_type == TDD)) {
295
296
297
298
299
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
knopp's avatar
   
knopp committed
300
  }
knopp's avatar
   
knopp committed
301

302
303
  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
304
	   (fp->frame_type == TDD)) { 
305
306
307
308
309
310
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }
knopp's avatar
   
knopp committed
311

312
}
knopp's avatar
   
knopp committed
313

314
315


316
317
318
319
320
321
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,
322
		      int ra_flag) {
323

324
325
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
326
327
  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
  int input_buffer_length = dlsch_harq->TBS/8;
328
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
329

330
  if (dlsch->rnti == 0x02) {//frame < 200) {
331

332
    LOG_D(PHY,
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
	  "[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);
  }    
353
#if defined(MESSAGE_CHART_GENERATOR_PHY)
354
355
356
  MSC_LOG_TX_MESSAGE(
		     MSC_PHY_ENB,MSC_PHY_UE,
		     NULL,0,
357
		     "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", TBS %"PRIu16", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
358
359
360
361
362
		     frame, subframe,
		     input_buffer_length,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
363
			   dlsch_harq->Qm,
364
			   dlsch_harq->Nl,
365
			   dlsch_harq->pdsch_start,
366
367
368
			   frame,
			   subframe,
			   dlsch_harq->mimo_mode==TM7?7:0),
369
		     dlsch_harq->nb_rb,
370
		     dlsch_harq->TBS,
371
372
373
374
		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
		     dlsch_harq->rvidx,
		     dlsch_harq->round);
#endif
375
376
  
  
377
  if (ue_stats) ue_stats->dlsch_sliding_cnt++;
378
  
379
380
381
  if (dlsch_harq->round == 0) {
    if (ue_stats)
      ue_stats->dlsch_trials[harq_pid][0]++;
382
383
384
385
386
387
388
389
  } 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
  }
390
391


392
393
  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);
394
  // 36-212 
395
396
397
398
399
400
401
402
403
404
  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,
405
	  dlsch_harq->pdu,
406
	  dlsch_harq->pdsch_start,
407
	  dlsch,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
408
409
	  frame,
	  subframe,
410
411
	  &eNB->dlsch_rate_matching_stats,
	  &eNB->dlsch_turbo_encoding_stats,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
412
	  &eNB->dlsch_turbo_encoding_waiting_stats,
413
      &eNB->dlsch_turbo_encoding_main_stats,
414
415
      &eNB->dlsch_turbo_encoding_wakeup_stats0,
      &eNB->dlsch_turbo_encoding_wakeup_stats1,
416
	  &eNB->dlsch_interleaving_stats);
417
    stop_meas(&eNB->dlsch_encoding_stats);
418
419
420
421
422
  //////////////////////////////////////////////////*******************************************
  if(eNB->dlsch_encoding_stats.diff_now>500*3000 && opp_enabled == 1)
  {
    print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
  }
423
  // 36-211
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
    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);

444
  
445
    dlsch_modulation(eNB,
446
447
		   eNB->common_vars.txdataF,
		   AMP,
jftt_wangshanshan's avatar
jftt_wangshanshan committed
448
		   frame,
449
		   subframe,
450
		   dlsch_harq->pdsch_start,
451
452
453
454
		   dlsch,
		   dlsch1);
  
  stop_meas(&eNB->dlsch_modulation_stats);
455
  }
456
#ifdef PHY_TX_THREAD
457
458
  dlsch->active[subframe] = 0;
#else
459
  dlsch->active = 0;
460
#endif
461
  dlsch_harq->round++;
462
463

  LOG_D(PHY,"Generating DLSCH/PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
464
}
465
466


467

knopp's avatar
knopp committed
468

469
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
knopp's avatar
knopp committed
470
			   eNB_rxtx_proc_t *proc,
471
			   int do_meas)
472
{
473
474
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
475
  uint32_t i,aa;
476
  uint8_t harq_pid;
477
  int16_t UE_id=0;
478
  uint8_t num_pdcch_symbols=0;
479
  uint8_t num_dci=0;
480
481
  uint8_t ul_subframe;
  uint32_t ul_frame;
482
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
483
  LTE_UL_eNB_HARQ_t *ulsch_harq;
484

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

knopp's avatar
knopp committed
487

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

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

493
  // clear the transmit data array for the current subframe
494
495
496
  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
497
  }
498
  
499

knopp's avatar
knopp committed
500

501
502
  if (nfapi_mode == 0 || nfapi_mode == 1) {
    if (is_pmch_subframe(frame,subframe,fp)) {
503
      pmch_procedures(eNB,proc);
504
505
506
507
508
    }
    else {
      // this is not a pmch subframe, so generate PSS/SSS/PBCH
      common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx);
    }
509
  }
510

knopp's avatar
knopp committed
511

knopp's avatar
   
knopp committed
512
  // clear existing ulsch dci allocations before applying info from MAC  (this is table
513
  ul_subframe = pdcch_alloc2ul_subframe(fp,subframe);
514
  ul_frame = pdcch_alloc2ul_frame(fp,frame,subframe);
515
516
517



knopp's avatar
   
knopp committed
518
  // clear previous allocation information for all UEs
519
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
520
521
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
knopp's avatar
   
knopp committed
522
  }
523

Cedric Roux's avatar
Cedric Roux committed
524
  /* save old HARQ information needed for PHICH generation */
525
526
527
  /* 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
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here
    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
555
556
557
558
      }
    }
  }

559

560

561
562
563
564
565
  //  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
566
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci);
567
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
568

569

570
571
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

572
  if (num_dci > 0)
Cedric Roux's avatar
Cedric Roux committed
573
574
    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);

575
576
577
578
579
580
581
582
583
584
585
586
587
588
  //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);
  }
589

590

gauthier's avatar
gauthier committed
591
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
592

593
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
knopp's avatar
   
knopp committed
594
  // Now scan UE specific DLSCH
595
  LTE_eNB_DLSCH_t *dlsch0,*dlsch1;
596
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
597
    {
598
599
600
601
602
      dlsch0 = eNB->dlsch[(uint8_t)UE_id][0]; 
      dlsch1 = eNB->dlsch[(uint8_t)UE_id][1]; 

      if ((dlsch0)&&
	  (dlsch0->rnti>0)&&
603
#ifdef PHY_TX_THREAD
604
605
	  (dlsch0->active[subframe] == 1)) {
#else
606
	  (dlsch0->active == 1)) {
607
#endif
608

609
	// get harq_pid
jftt_wangshanshan's avatar
jftt_wangshanshan committed
610
	harq_pid = dlsch0->harq_ids[frame%2][subframe];
611
	AssertFatal(harq_pid>=0,"harq_pid is negative\n");
612
613
614
615
616
617
618
619

        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
620

621
622
623
624
625
626
627
628
          pdsch_procedures(eNB,
              proc,
              harq_pid,
              dlsch0,
              dlsch1,
              &eNB->UE_stats[(uint32_t)UE_id],
              0);
        }
629
630


knopp's avatar
   
knopp committed
631
      }
632

gauthier's avatar
gauthier committed
633

634
635
      else if ((dlsch0)&&
	       (dlsch0->rnti>0)&&
636
#ifdef PHY_TX_THREAD
637
638
639
640
	       (dlsch0->active[subframe] == 0)) {
#else
           (dlsch0->active == 0)) {
#endif
641

642
643
        // 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
644
      }
knopp's avatar
   
knopp committed
645
    }
646
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
647

648
649


650
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,1);
651
652
653
  generate_phich_top(eNB,
		     proc,
		     AMP);
654
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,0);
655

Raymond Knopp's avatar
Raymond Knopp committed
656
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
657
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
658
  
659
660
}

661

662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
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;
      }
    }
  }
}

694
695
void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) {
  
696
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
697
698
699
700
701
702
703
704
  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;
705
706
707

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

711
  int SNRtimes10 = dB_fixed_times10(stat) - 300;//(10*eNB->measurements.n0_power_dB[0]);
712
713


714
715
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;

716
717
718
719
720
  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;

721
  sr_ind_body->number_of_srs++;
722
723
724
725
  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
726
{
727
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
728
  uint8_t SR_payload = 0,pucch_b0b1[4][2]= {{0,0},{0,0},{0,0},{0,0}},harq_ack[4]={0,0,0,0};
729
  int32_t metric[4]={0,0,0,0},metric_SR=0,max_metric=0;
730
731
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
732
733
734
  int i;
  LTE_eNB_UCI *uci;
  uint16_t tdd_multiplexing_mask=0;
735

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

738
739
740
741
    uci = &eNB->uci_vars[i];
    if ((uci->active == 1) &&
	(uci->frame == frame) &&
	(uci->subframe == subframe)) {
742

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

knopp's avatar
knopp committed
746
747
748
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
Cedric Roux's avatar
Cedric Roux committed
749
750
        eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
        break;
knopp's avatar
knopp committed
751
      case 15:
Cedric Roux's avatar
Cedric Roux committed
752
753
        eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
        break;
knopp's avatar
knopp committed
754
      case 25:
Cedric Roux's avatar
Cedric Roux committed
755
756
        eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
        break;
knopp's avatar
knopp committed
757
      case 50:
Cedric Roux's avatar
Cedric Roux committed
758
759
760
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
        break;
knopp's avatar
knopp committed
761
      case 75:
Cedric Roux's avatar
Cedric Roux committed
762
763
764
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
        break;
knopp's avatar
knopp committed
765
      case 100:
Cedric Roux's avatar
Cedric Roux committed
766
767
768
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
        break;
knopp's avatar
knopp committed
769
      default:
Cedric Roux's avatar
Cedric Roux committed
770
771
        LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
        break;
knopp's avatar
knopp committed
772
      }
Wu Jing's avatar
Wu Jing committed
773
      SR_payload = 0;
774
775
776
777
778
779
780
781
      switch (uci->type) {
      case SR:
      case HARQ_SR:
		
	metric_SR = rx_pucch(eNB,
			      uci->pucch_fmt,
			      i,
			      uci->n_pucch_1_0_sr[0],
782
			      0, // n2_pucch
783
			      uci->srs_active, // shortened format
784
785
786
787
			      &SR_payload,
			      frame,
			      subframe,
			      PUCCH1_THRES);
788
	LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (uci.type %d SR n1pucch is %d)\n",
789
	      eNB->Mod_id,
790
	      uci->rnti,
791
792
793
	      frame,
	      subframe,
	      SR_payload,
794
              uci->type,
795
796
797
	      uci->n_pucch_1_0_sr[0]);
	if (uci->type == SR) {
	  if (SR_payload == 1) {
798
	    fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
799
	    break;
800
801
	  }
	  else {
802
	    break;
803
804
805
806
	  }
	}
      case HARQ:
	if (fp->frame_type == FDD) {
807
	  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",
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
		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;
827
	  else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
 
	  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);
	  }
	  
845

846
	  LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
847
848
849
		eNB->Mod_id,
		uci->rnti,
		frame,subframe,
850
851
		pucch_b0b1[0][0],metric[0]);

852
      uci->stat = metric[0]; 	  
853
	  fill_uci_harq_indication(eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff);
854

855
856
	}
	else { // frame_type == TDD
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
#if 1
	      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);
	      if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0;
	      else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);

	      if (uci->type==HARQ_SR && metric[0] <= metric_SR) {
	          SR_payload = 1;
	          metric[0] = rx_pucch(eNB,
874
	                     pucch_format1b,
875
876
877
878
879
880
881
882
883
884
	                     i,
	                     uci->n_pucch_1_0_sr[0],
	                     0, //n2_pucch
	                     uci->srs_active, // shortened format
	                     pucch_b0b1[0],
	                     frame,
	                     subframe,
	                     PUCCH1a_THRES);
	      }
#else
885
886
	  // if SR was detected, use the n1_pucch from SR
	  if (SR_payload==1) {
887
#ifdef DEBUG_PHY_PROC
888
889
890
891
	    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);
892
#endif
893
894
895
896
897
898
899
900
901
902
903
904
	    
	    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
905
#ifdef DEBUG_PHY_PROC
906
907
908
909
910
911
912
913
914
	    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);
915
#endif
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
	    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);
	  	  
	    

	  }
Haruki Naoi's avatar
Haruki Naoi committed
931
932
#ifdef DEBUG_PHY_PROC
 	      LOG_D(PHY,"RNTI %x type %d SR_payload %d  Frame %d Subframe %d  pucch_b0b1[0][0] %d pucch_b0b1[0][1] %d pucch_b0b1[1][0] %d pucch_b0b1[1][1] %d  \n",
933
	              uci->rnti,uci->type,SR_payload,frame,subframe,pucch_b0b1[0][0],pucch_b0b1[0][1],pucch_b0b1[1][0],pucch_b0b1[1][1]);
Haruki Naoi's avatar
Haruki Naoi committed
934
935
#endif
#endif
936
937
938
939
	  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
	    }
940
	    else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1) { // 1/4/7 ACKs
941
942
	      harq_ack[0] = 1;
	    }
943
	    else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] != 1) { // 2/5/8 ACKs
944
945
	      harq_ack[0] = 2;
	    }
946
	    else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] == 1) { // 3/6/9 ACKs
947
948
	      harq_ack[0] = 3;
	    }
949
	    else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] != 1) { // 0 ACKs, or at least one DL assignment missed
950
951
	      harq_ack[0] = 0;
	    }
952
        uci->stat = metric[0];
953
954
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode
	  } 
knopp's avatar
knopp committed
955
	  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
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
	    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
		}
	      }
	    }
994
        uci->stat = max(metric[0],metric[1]);
995
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
knopp's avatar
knopp committed
996
	  } //else if ((uci->tdd_bundling == 0) && (res==2))
knopp's avatar
knopp committed
997
	  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
998
999
1000
1001
1002
1003
1004
	    
	    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
1005
              max_metric = 0;
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
	    } 
	    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;
		}
	      }
1075
            uci->stat = max_metric;
1076
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
1077
	    }
knopp's avatar
knopp committed
1078
	  } //else if ((uci->tdd_bundling == 0) && (res==3)) 
knopp's avatar
knopp committed
1079
	  else if ((uci->tdd_bundlin