phy_procedures_lte_eNb.c 74.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
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"
37
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
38
#include "nfapi_interface.h"
39
#include "fapi_l1.h"
40 41
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
42

43
#include "assertions.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
44
#include "msc.h"
45

46 47
#include <time.h>

48
#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
Raymond Knopp committed
49
#include "intertask_interface.h"
50 51
#endif

52
extern uint8_t nfapi_mode;
53

Raymond Knopp's avatar
 
Raymond Knopp committed
54

55

Wang Tsu-Han's avatar
Wang Tsu-Han committed
56
int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t UE_id,uint8_t harq_pid, uint8_t bw_factor)
Raymond Knopp's avatar
Raymond Knopp committed
57
{
58

59 60 61 62 63 64 65
  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 *
66
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12;
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

  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 );
90
  //#warning "This condition happens sometimes. Need more investigation" // navid
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
  //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)
{
108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
  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 );
}

126
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind);
127

Raymond Knopp's avatar
 
Raymond Knopp committed
128

129 130
lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subframe)
{
131

132
  return(subframe_select(&RC.eNB[Mod_id][CC_id]->frame_parms,subframe));
133

134
}
135

136
void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
137 138


139
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
Raymond Knopp's avatar
Raymond Knopp committed
140
  MCH_PDU *mch_pduP=NULL;
141
  //  uint8_t sync_area=255;
142
#endif
143

Raymond Knopp's avatar
Raymond Knopp committed
144
  int             subframe = proc->subframe_tx;
145

Raymond Knopp's avatar
Raymond Knopp committed
146
  AssertFatal (1 == 0, "pmch not tested for the moment, exiting\n");
Raymond Knopp's avatar
Raymond Knopp committed
147

148
  // This is DL-Cell spec pilots in Control region
Raymond Knopp's avatar
Raymond Knopp committed
149 150
  generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1);

151

152
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
153 154
  // 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
155
  /*
156 157 158 159 160
    mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id,
    eNB->CC_id,
    proc->frame_tx,
    subframe);
  */
161 162 163 164 165 166 167 168
  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");
Raymond Knopp's avatar
Raymond Knopp committed
169
    mch_pduP = NULL;
170
  }
171 172
    
  if (mch_pduP) {
Raymond Knopp's avatar
Raymond Knopp committed
173
    fill_eNB_dlsch_MCH (eNB, mch_pduP->mcs, 1, 0);
174
    // Generate PMCH
Raymond Knopp's avatar
Raymond Knopp committed
175
    generate_mch (eNB, proc, (uint8_t *) mch_pduP->payload);
176
  } else {
Raymond Knopp's avatar
Raymond Knopp committed
177
    LOG_D (PHY, "[eNB/RN] Frame %d subframe %d: MCH not generated \n", proc->frame_tx, subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
178
  }
Raymond Knopp's avatar
Raymond Knopp committed
179

180
#endif
181
}
182

183
void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
184

185
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
186
  int **txdataF = eNB->common_vars.txdataF;
187
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
188

189
  //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?"); 
190

191
  // generate Cell-Specific Reference Signals for both slots
192
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
193

194
  if(subframe_select(fp,subframe) == SF_S)
195 196 197
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
198 199 200 201 202 203 204
			 subframe<<1,1);
  else
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
			 subframe<<1,0);

205
  // check that 2nd slot is for DL
Raymond Knopp's avatar
Raymond Knopp committed
206 207 208 209 210
  if (subframe_select (fp, subframe) == SF_DL)
    generate_pilots_slot (eNB, txdataF, AMP, (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)
Raymond Knopp's avatar
 
Raymond Knopp committed
213
  if (subframe == 0) {
214
    if (fp->frame_type == FDD) {
Raymond Knopp's avatar
Raymond Knopp committed
215 216 217
      generate_pss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 0);
      generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 5 : 4, 0);

218
    }
219 220


Raymond Knopp's avatar
Raymond Knopp committed
221

222
    /// First half of SSS (TDD, slot 1)
Raymond Knopp's avatar
Raymond Knopp committed
223

224
    if (fp->frame_type == TDD) {
Raymond Knopp's avatar
Raymond Knopp committed
225
      generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 1);
226
    }
227 228
    // generate PBCH (Physical Broadcast CHannel) info

229
    /// generate PBCH
230
    if ((frame&3)==0) {
231 232
      //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n");
      if (eNB->pbch_configured!=1) return;
233
      eNB->pbch_configured=0;
234
    }
235 236
    T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
      T_BUFFER(pbch_pdu, 3));
237

Raymond Knopp's avatar
Raymond Knopp committed
238 239 240 241
    generate_pbch (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, frame & 3);

  } else if ((subframe == 1) && (fp->frame_type == TDD)) {
    generate_pss (txdataF, AMP, fp, 2, 2);
242
  }
243
  // Second half of PSS/SSS (FDD, slot 10)
Raymond Knopp's avatar
Raymond Knopp committed
244 245 246
  else if ((subframe == 5) && (fp->frame_type == FDD)) {
    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);
247

248 249
  }
  //  Second-half of SSS (TDD, slot 11)
Raymond Knopp's avatar
Raymond Knopp committed
250 251
  else if ((subframe == 5) && (fp->frame_type == TDD)) {
    generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 11);
Raymond Knopp's avatar
 
Raymond Knopp committed
252
  }
253
  // Second half of PSS (TDD, slot 12)
Raymond Knopp's avatar
Raymond Knopp committed
254 255
  else if ((subframe == 6) && (fp->frame_type == TDD)) {
    generate_pss (txdataF, AMP, fp, 2, 12);
256
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
257

258
}
Raymond Knopp's avatar
 
Raymond Knopp committed
259

260

261

262
void pdsch_procedures(PHY_VARS_eNB *eNB,
263
		      L1_rxtx_proc_t *proc,
264 265 266 267
		      int harq_pid,
		      LTE_eNB_DLSCH_t *dlsch, 
		      LTE_eNB_DLSCH_t *dlsch1,
		      LTE_eNB_UE_stats *ue_stats,
268
		      int ra_flag) {
269

270 271
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
272
  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
273
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
274

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

nepes's avatar
nepes committed
277
    LOG_D(PHY,
278 279
	  "[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,
280
	  frame, subframe, dlsch_harq->TBS/8, dlsch_harq->pdsch_start,
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
	  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);
  }    
298

299 300 301
  MSC_LOG_TX_MESSAGE(
		     MSC_PHY_ENB,MSC_PHY_UE,
		     NULL,0,
302
		     "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", TBS %"PRIu16", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
303
		     frame, subframe,
304
		     dlsch_harq->TBS/8,
305 306 307
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
308
			   dlsch_harq->Qm,
309
			   dlsch_harq->Nl,
310
			   dlsch_harq->pdsch_start,
311 312 313
			   frame,
			   subframe,
			   dlsch_harq->mimo_mode==TM7?7:0),
314
		     dlsch_harq->nb_rb,
315
		     dlsch_harq->TBS,
316 317 318
		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
		     dlsch_harq->rvidx,
		     dlsch_harq->round);
Raymond Knopp's avatar
Raymond Knopp committed
319

320 321
  
  
322
  if (ue_stats) ue_stats->dlsch_sliding_cnt++;
323
  
324 325 326
  if (dlsch_harq->round == 0) {
    if (ue_stats)
      ue_stats->dlsch_trials[harq_pid][0]++;
327 328 329 330
  } else {
    ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++;
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
Raymond Knopp's avatar
Raymond Knopp committed
331
    LOG_D (PHY, "[eNB] This DLSCH is a retransmission\n");
332 333 334
#endif
#endif
  }
335 336


nepes's avatar
nepes committed
337
  if (dlsch->rnti!=0xffff) 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",
338
	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);
339
  // 36-212 
340
  if (nfapi_mode == 0 || nfapi_mode == 1) { // monolthic OR PNF - do not need turbo encoding on VNF
Raymond Knopp's avatar
Raymond Knopp committed
341

342
    if (dlsch_harq->pdu==NULL){
343
      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]);
344 345
      return;
    }
Raymond Knopp's avatar
Raymond Knopp committed
346

347 348
    start_meas(&eNB->dlsch_encoding_stats);

laurent's avatar
laurent committed
349
    dlsch_encoding_all(eNB,
350 351 352 353 354 355 356 357 358 359 360 361 362
		       dlsch_harq->pdu,
		       dlsch_harq->pdsch_start,
		       dlsch,
		       frame,
		       subframe,
		       &eNB->dlsch_rate_matching_stats,
		       &eNB->dlsch_turbo_encoding_stats,
		       &eNB->dlsch_turbo_encoding_waiting_stats,
		       &eNB->dlsch_turbo_encoding_main_stats,
		       &eNB->dlsch_turbo_encoding_wakeup_stats0,
		       &eNB->dlsch_turbo_encoding_wakeup_stats1,
		       &eNB->dlsch_interleaving_stats);

363
    stop_meas(&eNB->dlsch_encoding_stats);
364 365 366 367 368
    if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1)
      {
	print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
      }
    // 36-211
369 370
    start_meas(&eNB->dlsch_scrambling_stats);
    dlsch_scrambling(fp,
371 372 373 374 375 376 377 378 379 380 381 382 383 384
		     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);
385 386 387
    stop_meas(&eNB->dlsch_scrambling_stats);

    start_meas(&eNB->dlsch_modulation_stats);
388

389
  
390
    dlsch_modulation(eNB,
391 392 393 394 395 396 397 398 399
		     eNB->common_vars.txdataF,
		     AMP,
		     frame,
		     subframe,
		     dlsch_harq->pdsch_start,
		     dlsch,
		     dlsch1);
  
    stop_meas(&eNB->dlsch_modulation_stats);
400
  }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
401 402 403
#ifdef PHY_TX_THREAD
  dlsch->active[subframe] = 0;
#else
404
  dlsch->active = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
405
#endif
406
  dlsch_harq->round++;
sharma's avatar
sharma committed
407

408
  LOG_D(PHY,"Generating DLSCH/PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
409
}
410 411 412



413
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
414
			   L1_rxtx_proc_t *proc,
415
			   int do_meas)
416
{
417 418
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
419
  uint32_t i,aa;
420
  uint8_t harq_pid;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
421
  int16_t UE_id=0;
422
  uint8_t num_pdcch_symbols=0;
423
  uint8_t num_dci=0;
424
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
425 426
  uint8_t         num_mdci = 0;
#endif
427 428
  uint8_t ul_subframe;
  uint32_t ul_frame;
429
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
430
  LTE_UL_eNB_HARQ_t *ulsch_harq;
431

432

433

Raymond Knopp's avatar
Raymond Knopp committed
434 435
  if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL))
    return;
436

437
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(eNB->CC_id),1);
438
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
laurent's avatar
laurent committed
439
  if (do_meas==1) start_meas(&eNB->dlsch_common_and_dci);
440

441
  // clear the transmit data array for the current subframe
Raymond Knopp's avatar
Raymond Knopp committed
442 443
  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));
Raymond Knopp's avatar
 
Raymond Knopp committed
444
  }
445
  
446
  
447 448
  if (nfapi_mode == 0 || nfapi_mode == 1) {
    if (is_pmch_subframe(frame,subframe,fp)) {
449
      pmch_procedures(eNB,proc);
450 451 452 453 454
    }
    else {
      // this is not a pmch subframe, so generate PSS/SSS/PBCH
      common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx);
    }
455
  }
456 457
  
  
Raymond Knopp's avatar
 
Raymond Knopp committed
458
  // clear existing ulsch dci allocations before applying info from MAC  (this is table
Raymond Knopp's avatar
Raymond Knopp committed
459 460
  ul_subframe = pdcch_alloc2ul_subframe (fp, subframe);
  ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe);
461 462 463
  
  
  
Raymond Knopp's avatar
 
Raymond Knopp committed
464
  // clear previous allocation information for all UEs
Raymond Knopp's avatar
Raymond Knopp committed
465
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
466 467
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
468
  }
469 470
  
  
471 472 473 474
  /* 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
475
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
476
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
477
      if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0;
478 479
      else 
#endif
480 481
	harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
      
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
      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;
504
	ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS;
505
	
506 507 508
      }
    }
  }
509 510
  
  
511 512
  num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols;
  num_dci           = eNB->pdcch_vars[subframe&1].num_dci;
Cedric Roux's avatar
Cedric Roux committed
513
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci);
514
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
515
  
Raymond Knopp's avatar
Raymond Knopp committed
516
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME (VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO, (frame * 10) + subframe);
517
  
518
  if (num_dci > 0)
Cedric Roux's avatar
Cedric Roux committed
519
    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);
520
  
521
  
522
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
523
  
524 525
  if (nfapi_mode == 0 || nfapi_mode == 1) {
    generate_dci_top(num_pdcch_symbols,
526 527 528 529 530 531 532
		     num_dci,
		     &eNB->pdcch_vars[subframe&1].dci_alloc[0],
		     0,
		     AMP,
		     fp,
		     eNB->common_vars.txdataF,
		     subframe);
533
    
534
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
535 536
    num_mdci = eNB->mpdcch_vars[subframe &1].num_dci;
    if (num_mdci > 0) {
nepes's avatar
nepes committed
537
      LOG_D (PHY, "[eNB %" PRIu8 "] Frame %d, subframe %d: Calling generate_mdci_top (mpdcch) (num_dci %" PRIu8 ")\n", eNB->Mod_id, frame, subframe, num_mdci);
538 539 540
      
      generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF);
      
541
    }
542
#endif
543
  }
544

laurent's avatar
laurent committed
545
  if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci);
laurent's avatar
laurent committed
546
  if (do_meas==1) start_meas(&eNB->dlsch_ue_specific);
547

548
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
549

550
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
551
  // Now scan UE specific DLSCH
552
  LTE_eNB_DLSCH_t *dlsch0,*dlsch1;
553 554 555 556 557
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
    dlsch0 = eNB->dlsch[(uint8_t)UE_id][0]; 
    dlsch1 = eNB->dlsch[(uint8_t)UE_id][1]; 
    
    if ((dlsch0)&&(dlsch0->rnti>0)&&
Wang Tsu-Han's avatar
Wang Tsu-Han committed
558
#ifdef PHY_TX_THREAD
559
	(dlsch0->active[subframe] == 1) 
Wang Tsu-Han's avatar
Wang Tsu-Han committed
560
#else
561
	(dlsch0->active == 1) 
562
#endif
563 564 565 566 567 568
	){
      
      // get harq_pid
      harq_pid = dlsch0->harq_ids[frame%2][subframe];
      AssertFatal(harq_pid>=0,"harq_pid is negative\n");
      
nepes's avatar
nepes committed
569 570 571 572 573
      if (harq_pid>=8) {

#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
        if (dlsch0->ue_type==0) 
#endif
nepes's avatar
nepes committed
574 575 576 577 578 579 580 581 582
	  LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x [ %1d.%1d.%1d.%1d.%1d.%1d.%1d.%1d\n", harq_pid,UE_id,frame,subframe,dlsch0->rnti,
                dlsch0->harq_ids[frame%2][0],
                dlsch0->harq_ids[frame%2][1],
                dlsch0->harq_ids[frame%2][2],
                dlsch0->harq_ids[frame%2][3],
                dlsch0->harq_ids[frame%2][4],
                dlsch0->harq_ids[frame%2][5],
                dlsch0->harq_ids[frame%2][6],
                dlsch0->harq_ids[frame%2][7]);
nepes's avatar
nepes committed
583 584
      } else
      {
585 586 587 588 589 590 591 592 593
	  // generate pdsch
	  
	  pdsch_procedures(eNB,
			   proc,
			   harq_pid,
			   dlsch0,
			   dlsch1,
			   &eNB->UE_stats[(uint32_t)UE_id],
			   0);
nepes's avatar
nepes committed
594
      }
595 596
      
      
597
    }
598 599 600
    
    
    else if ((dlsch0)&&(dlsch0->rnti>0)&&
Wang Tsu-Han's avatar
Wang Tsu-Han committed
601
#ifdef PHY_TX_THREAD
602
	     (dlsch0->active[subframe] == 0) 
Wang Tsu-Han's avatar
Wang Tsu-Han committed
603
#else
604
	     (dlsch0->active == 0) 
605
#endif
606 607 608
	     ){
      // 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;
Raymond Knopp's avatar
 
Raymond Knopp committed
609
    }
610 611 612 613 614
    
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
    
  }
  
615
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,1);
616 617 618
  generate_phich_top(eNB,
		     proc,
		     AMP);
619
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,0);
620
  
621
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(eNB->CC_id),0);
laurent's avatar
laurent committed
622
  if (do_meas==1) stop_meas(&eNB->dlsch_ue_specific);
623
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
624
  
625 626
}

627

628
void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
629 630

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
Raymond Knopp's avatar
Raymond Knopp committed
631 632
  const int       subframe = proc->subframe_rx;
  const int       frame = proc->frame_rx;
633
  
Raymond Knopp's avatar
Raymond Knopp committed
634
  int             i;
635
  
Raymond Knopp's avatar
Raymond Knopp committed
636
  if (is_srs_occasion_common (fp, frame, subframe)) {
637
    
Raymond Knopp's avatar
Raymond Knopp committed
638 639 640 641
    // 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++) {
642
      
Raymond Knopp's avatar
Raymond Knopp committed
643
      if (eNB->soundingrs_ul_config_dedicated[i].active == 1) {
644 645 646 647
	
	
	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");
648
	}
649
	eNB->soundingrs_ul_config_dedicated[i].active = 0;
650 651 652 653 654
      }
    }
  }
}

655 656
void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) {
  
657
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
658 659 660
  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];
661
  
662 663
  sr_ind->sfn_sf = frame<<4|subframe;
  sr_ind->header.message_id = NFAPI_RX_SR_INDICATION;
664
  
665
  sr_ind_body->tl.tag = NFAPI_SR_INDICATION_BODY_TAG;
666
  
667 668
  pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
669
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
670
  pdu->rx_ue_information.rnti                         = rnti;
671
  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
672
  int SNRtimes10 = dB_fixed_times10(stat) - 300;//(10*eNB->measurements.n0_power_dB[0]);
673

674

675

676 677
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
  
678 679 680 681
  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;
682
  
683
  sr_ind_body->number_of_srs++;
684 685 686
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}

687
void uci_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc)
Cedric Roux's avatar
Cedric Roux committed
688
{
689
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
690
  uint8_t SR_payload = 0,pucch_b0b1[4][2]= {{0,0},{0,0},{0,0},{0,0}},harq_ack[4]={0,0,0,0};
691
  int32_t metric[4]={0,0,0,0},metric_SR=0,max_metric=0;
692 693
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
694 695 696
  int i;
  LTE_eNB_UCI *uci;
  uint16_t tdd_multiplexing_mask=0;
697
  
698
  for (i=0;i<NUMBER_OF_UE_MAX;i++) {
699 700
    
    
701
    uci = &eNB->uci_vars[i];
Raymond Knopp's avatar
Raymond Knopp committed
702
    if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) {
703
      
Raymond Knopp's avatar
Raymond Knopp committed
704 705
      LOG_D (PHY, "Frame %d, subframe %d: Running uci procedures (type %d) for %d \n", frame, subframe, uci->type, i);
      uci->active = 0;
706
      
707
      // Null out PUCCH PRBs for noise measurement
Raymond Knopp's avatar
Raymond Knopp committed
708
      switch (fp->N_RB_UL) {
709
      case 6:
710 711
	eNB->rb_mask_ul[0] |= (0x1 | (1 << 5)); //position 5
	break;
712
      case 15:
713 714
	eNB->rb_mask_ul[0] |= (0x1 | (1 << 14));        // position 14
	break;
715
      case 25:
716 717
	eNB->rb_mask_ul[0] |= (0x1 | (1 << 24));        // position 24
	break;
718
      case 50:
719 720 721
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[1] |= (1 << 17);        // position 49 (49-32)
	break;
722
      case 75:
723 724 725
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[2] |= (1 << 10);        // position 74 (74-64)
	break;
726
      case 100:
727 728 729
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[3] |= (1 << 3); // position 99 (99-96)
	break;
730
      default:
731 732
	LOG_E (PHY, "Unknown number for N_RB_UL %d\n", fp->N_RB_UL);
	break;
733
      }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
734
      SR_payload = 0;
735 736 737
      switch (uci->type) {
      case SR:
      case HARQ_SR:
sharma's avatar
sharma committed
738
	
739
	metric_SR = rx_pucch(eNB,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
740 741 742 743 744 745 746 747
			     uci->pucch_fmt,
			     i,
			     uci->n_pucch_1_0_sr[0],
			     0, // n2_pucch
			     uci->srs_active, // shortened format
			     &SR_payload,
			     frame,
			     subframe,
nepes's avatar
nepes committed
748 749 750 751 752
			     PUCCH1_THRES
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) 
			     ,uci->ue_type
#endif
                             );
Wang Tsu-Han's avatar
Wang Tsu-Han committed
753
	LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (uci.type %d SR n1pucch is %d)\n",
754
	      eNB->Mod_id,
755
	      uci->rnti,
756 757 758
	      frame,
	      subframe,
	      SR_payload,
759
	      uci->type,
760 761 762
	      uci->n_pucch_1_0_sr[0]);
	if (uci->type == SR) {
	  if (SR_payload == 1) {
763
	    fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
764
	    break;
765 766
	  }
	  else {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
767
	    break;
768 769 770 771
	  }
	}
      case HARQ:
	if (fp->frame_type == FDD) {
nepes's avatar
nepes committed
772
	  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",
773 774 775 776 777 778 779 780 781 782 783 784 785 786
		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,
nepes's avatar
nepes committed
787 788 789 790 791
			       PUCCH1a_THRES
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) 
                               ,uci->ue_type
#endif
                               );
792
          //dump_ulsch(eNB,frame,subframe,0,0); exit(-1);
793 794 795 796
	  
	  
	  /* 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;
797
	  else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
798
	  
799 800 801 802 803 804 805 806 807 808 809 810 811
	  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,
nepes's avatar
nepes committed
812 813 814 815 816
			       PUCCH1a_THRES
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) 
                               ,uci->ue_type
#endif
                               );
817 818
	  }
	  
819
	  
nepes's avatar
nepes committed
820
	  LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
821 822 823
		eNB->Mod_id,
		uci->rnti,
		frame,subframe,
824
		pucch_b0b1[0][0],metric[0]);
825
	  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
826
	  uci->stat = metric[0]; 	  
827
	  fill_uci_harq_indication(eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff);
828
	  
829 830
	}
	else { // frame_type == TDD
Wang Tsu-Han's avatar
Wang Tsu-Han committed
831 832 833 834 835 836
	  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",
		frame,subframe,i,
		uci->pucch_fmt,uci->type,
		uci->frame,uci->subframe,uci->n_pucch_1[0][0],
		SR_payload);
#if 1
837 838 839 840 841 842 843 844 845
	  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,
nepes's avatar
nepes committed
846 847 848 849 850 851
			       PUCCH1a_THRES
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) 
                               ,uci->ue_type
#endif
                               );

852 853 854 855 856
	  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;
857 858 859 860 861 862 863 864 865
	    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,
nepes's avatar
nepes committed
866 867 868 869 870 871
				 PUCCH1a_THRES
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) 
                                ,uci->ue_type
#endif
                                 );

872 873 874 875
	  }
#else
	  // if SR was detected, use the n1_pucch from SR
	  if (SR_payload==1) {
876
#ifdef DEBUG_PHY_PROC
877 878
	    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);
879
#endif
880 881 882 883
	    
	    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
884
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
sharma's avatar
sharma committed
885 886 887
				  ,uci->ue_type
#endif
				  );
888
	  } else {              //using assigned pucch resources
889
#ifdef DEBUG_PHY_PROC
890 891 892
	    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);
893
#endif
894 895 896 897
	    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
898
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
899 900 901
				      ,uci->ue_type
#endif		  
				      );
902 903 904 905 906 907 908 909 910 911
	    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,
912
				     PUCCH1a_THRES,
913
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
914 915 916
				     ,uci->ue_type
#endif		  
				     );
917
	  }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
918
#ifdef DEBUG_PHY_PROC
919 920
	  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",
		uci->rnti,uci->type,SR_payload,frame,subframe,pucch_b0b1[0][0],pucch_b0b1[0][1],pucch_b0b1[1][0],pucch_b0b1[1][1]);
sharma's avatar
sharma committed
921
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
922
#endif
923 924 925 926
	  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
	    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
927
	    else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1) { // 1/4/7 ACKs
928 929
	      harq_ack[0] = 1;
	    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
930
	    else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] != 1) { // 2/5/8 ACKs
931 932
	      harq_ack[0] = 2;
	    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
933
	    else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] == 1) { // 3/6/9 ACKs
934 935
	      harq_ack[0] = 3;
	    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
936
	    else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] != 1) { // 0 ACKs, or at least one DL assignment missed
937 938
	      harq_ack[0] = 0;
	    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
939
	    uci->stat = metric[0];
940 941
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode
	  } 
Raymond Knopp's avatar
Raymond Knopp committed
942
	  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
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
	    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
		}
	      }
	    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
981
	    uci->stat = max(metric[0],metric[1]);
982
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
983
	  } //else if ((uci->tdd_bundling == 0) && (res==2))
Raymond Knopp's avatar
Raymond Knopp committed
984
	  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
985 986 987 988 989 990 991
	    
	    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
992
	      max_metric = 0;
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
	    } 
	    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) {
1017 1018
		
		if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] != 1){
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
		  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 {
1037
		if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] == 1){
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
		  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;
		}
	      }
1062 1063
	      uci->stat = max_metric;
	      fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
1064
	    }
1065
	  } //else if ((uci->tdd_bundling == 0) && (res==3)) 
Raymond Knopp's avatar
Raymond Knopp committed
1066
	  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
1067 1068 1069 1070 1071 1072 1073 1074
	    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
1075
	      max_metric = 0;
1076
	    } else {
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 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
	      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;
		}
	      }
	    }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1200
	    uci->stat = max_metric;
1201
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
1202
	  } // else if ((uci->tdd_bundling == 0) && (res==4))
1203 1204 1205
	  else { // bundling
	    harq_ack[0] = pucch_b0b1[0][0];
	    harq_ack[1] = pucch_b0b1[0][1];
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1206 1207
	    uci->stat = metric[0];
	    LOG_D(PHY,"bundling: (%d,%d), metric %d\n",harq_ack[0],harq_ack[1],uci->stat);
1208 1209
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode
	  }
1210
	  
1211
#ifdef DEBUG_PHY_PROC
1212 1213
	  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,
		 eNB->dlsch[UE_id][0]->rnti, frame, subframe, metric0, metric1, pucch_b0b1[0], pucch_b0b1[1]);
1214
#endif
1215 1216 1217
	}
	break;
      default:
1218
	AssertFatal (1 == 0, "Unsupported UCI type %d\n", uci->type);
1219
	break;
Cedric Roux's avatar
Cedric Roux committed
1220
      }
1221
      
1222
      if (SR_payload == 1) {
1223
	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);
1224
	
1225
	if (eNB->first_sr[i] == 1) {    // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
1226
	  eNB->first_sr[i] = 0;
1227 1228 1229
	  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);
1230
	}
Cedric Roux's avatar
Cedric Roux committed
1231 1232 1233
      }
    }
  }
1234
}
1235

1236
void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc)
Cedric Roux's avatar
Cedric Roux committed
1237
{
Raymond Knopp's avatar
Raymond Knopp committed
1238 1239
  uint32_t ret=0,i;
  uint32_t harq_pid;
1240 1241 1242 1243
  uint8_t nPRS;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  LTE_eNB_ULSCH_t *ulsch;
  LTE_UL_eNB_HARQ_t *ulsch_harq;
1244
  
1245 1246
  const int subframe = proc->subframe_rx;
  const int frame    = proc->frame_rx;
1247
  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1248
  harq_pid = subframe2harq_pid(&eNB->frame_parms,frame,subframe);
1249

1250
  
Raymond Knopp's avatar
Raymond Knopp committed
1251
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
1252
    ulsch = eNB->ulsch[i];
1253
    if (ulsch->ue_type > 0) harq_pid = 0;
1254
    
1255
    ulsch_harq = ulsch->harq_processes[harq_pid];
1256
    
1257 1258
    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,
1259
			     ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled);
1260
    
1261
    if ((ulsch) &&
1262 1263 1264 1265 1266
	(ulsch->rnti>0) &&
	(ulsch_harq->status == ACTIVE) &&
	(ulsch_harq->frame == frame) &&
	(ulsch_harq->subframe == subframe) &&
	(ulsch_harq->handled == 0)) {
1267
      
1268
      // UE has ULSCH scheduling
1269
      for (int rb=0;
1270
	   rb<=ulsch_harq->nb_rb;
1271 1272 1273
	   rb++) {
	int rb2 = rb+ulsch_harq->first_rb;
	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
1274
      }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1275
      
Cedric Roux's avatar
Cedric Roux committed
1276
      LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", eNB->Mod_id, frame, subframe, i);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1277
      
1278
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1279
      
Cedric Roux's avatar
Cedric Roux committed
1280
      ulsch->cyclicShift = (ulsch_harq->n_DMRS2 +
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1281 1282 1283
			    fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
			    nPRS)%12;
      AssertFatal(ulsch_harq->TBS>0,"illegal TBS %d\n",ulsch_harq->TBS); 
1284
      LOG_D(PHY,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
	    "[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);
      
      rx_ulsch(eNB,proc, i);
      
      stop_meas(&eNB->ulsch_demodulation_stats);
      
      start_meas(&eNB->ulsch_decoding_stats);
      
      ret = ulsch_decoding(eNB,proc,
			   i,
			   0, // control_only_flag
			   ulsch_harq->V_UL_DAI,
			   ulsch_harq->nb_rb>20 ? 1 : 0);
      
      stop_meas(&eNB->ulsch_decoding_stats);
      
nepes's avatar
nepes committed
1317
      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",
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
	    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]),
	    30,//eNB->measurements.n0_power_dB[0],
	    30,//eNB->measurements.n0_power_dB[1],
	    ulsch_harq->o_ACK[0],
	    ulsch_harq->o_ACK[1],
	    ret,
	    ulsch_harq->cqi_crc_status,
	    ulsch_harq->O_ACK,
	    eNB->ulsch_decoding_stats.p_time, eNB->ulsch_decoding_stats.max);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1331
      
1332
      //compute the expected ULSCH RX power (for the stats)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1333 1334
      ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
      
1335
      if (RC.mac != NULL) { /* ulsim dose not use RC.mac context. */
1336
	if (ulsch_harq->cqi_crc_status == 1) {
1337
#ifdef DEBUG_PHY_PROC
1338 1339
	  //if (((frame%10) == 0) || (frame < 50))
	  print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL);
1340
#endif
1341 1342 1343 1344 1345 1346 1347 1348 1349
	  fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti);
	  RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe));
	} else {
	  if(RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ){
	    RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe));
	    RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_timer=30;
	    LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",frame,subframe);
	  }
	}
1350
      }
1351
      
1352
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1353 1354 1355
	T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti),
	  T_INT(harq_pid));
	
1356 1357
	fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC
	fill_rx_indication(eNB,i,frame,subframe);  // indicate SDU to MAC
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1358
	
1359 1360 1361
	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,
1362
	      ulsch_harq->round,
1363 1364 1365
	      ulsch->Mlimit,
	      ulsch_harq->o_ACK[0],
	      ulsch_harq->o_ACK[1]);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1366
	
1367
	if (ulsch_harq->round >= 3)  {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1368 1369 1370 1371 1372
	  ulsch_harq->status  = SCH_IDLE;
	  ulsch_harq->handled = 0;
	  ulsch->harq_mask   &= ~(1 << harq_pid);
	  ulsch_harq->round   = 0;
	}
1373 1374
	
	MSC_LOG_RX_DISCARDED_MESSAGE(
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1375 1376 1377 1378 1379 1380 1381 1382
				     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
				     );
	
1383 1384 1385 1386 1387 1388
	/* 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;
Raymond Knopp's avatar
Raymond Knopp committed
1389
      }                         // ulsch in error
1390
      else {
1391 1392
	fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC
	fill_rx_indication(eNB,i,frame,subframe);  // indicate SDU to MAC
1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
	ulsch_harq->status = SCH_IDLE;
	ulsch->harq_mask &= ~(1 << harq_pid);
	
	T (T_ENB_PHY_ULSCH_UE_ACK, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (ulsch->rnti), T_INT (harq_pid));

	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
			   );
	
	
1407
#ifdef DEBUG_PHY_PROC
1408
#ifdef DEBUG_ULSCH
1409 1410 1411 1412 1413 1414 1415
	LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
	      harq_pid,ulsch_harq->TBS>>3);
	
	for (j=0; j<ulsch_harq->TBS>>3; j++)
	  LOG_T(PHY,"%x.",ulsch->harq_processes[harq_pid]->b[j]);
	
	LOG_T(PHY,"\n");
1416
#endif
1417
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1418
      }  // ulsch not in error
1419
      
1420
      if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,frame,subframe,ulsch->bundling);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1421
      
1422
      LOG_D(PHY,"[eNB %d] Frame %d subframe %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n",
1423 1424 1425 1426 1427 1428 1429 1430 1431
	    eNB->Mod_id,frame,subframe,
	    harq_pid,
	    i,
	    ret,
	    ulsch_harq->cqi_crc_status,
	    ulsch_harq->o_ACK[0],
	    ulsch_harq->o_ACK[1],
	    eNB->UE_stats[i].ulsch_errors[harq_pid],
	    eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]);
1432
    } //     if ((ulsch) &&
Raymond Knopp's avatar
Raymond Knopp committed
1433 1434
    //         (ulsch->rnti>0) &&
    //         (ulsch_harq->status == ACTIVE))
1435
    else if ((ulsch) &&
1436 1437 1438 1439 1440
	     (ulsch->rnti>0) &&
	     (ulsch_harq->status == ACTIVE) &&
	     (ulsch_harq->frame == frame) &&
	     (ulsch_harq->subframe == subframe) &&
	     (ulsch_harq->handled == 1)) {
Cedric Roux's avatar
Cedric Roux committed
1441 1442 1443
      // this harq process is stale, kill it, this 1024 frames later (10s), consider reducing that
      ulsch_harq->status = SCH_IDLE;
      ulsch_harq->handled = 0;
Raymond Knopp's avatar
Raymond Knopp committed
1444 1445
      ulsch->harq_mask &= ~(1 << harq_pid);
      LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask);
1446
    }
1447
  }   //   for (i=0; i<NUMBER_OF_UE_MAX; i++)
1448
}
1449

Raymond Knopp's avatar
Raymond Knopp committed
1450
extern int      oai_exit;
1451

Raymond Knopp's avatar
Raymond Knopp committed
1452
extern void    *td_thread (void *);
1453

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1454
void init_td_thread(PHY_VARS_eNB *eNB) {
1455

1456
  L1_proc_t *proc = &eNB->proc;
1457

1458
  proc->tdp.eNB = eNB;
1459
  proc->instance_cnt_td         = -1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1460 1461
  
  pthread_attr_init( &proc->attr_td);  
1462 1463
  pthread_mutex_init( &proc->mutex_td, NULL);
  pthread_cond_init( &proc->cond_td, NULL);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1464 1465
  
  pthread_create(&proc->pthread_td, &proc->attr_td, td_thread, (void*)&proc->tdp);
1466
  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1467 1468
}
void kill_td_thread(PHY_VARS_eNB *eNB) {
1469

1470
  L1_proc_t *proc = &eNB->proc;
1471

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1472 1473 1474 1475 1476 1477
  proc->instance_cnt_td         = 0;
  pthread_cond_signal(&proc->cond_td);
  
  pthread_join(proc->pthread_td, NULL);
  pthread_mutex_destroy( &proc->mutex_td );
  pthread_cond_destroy( &proc->cond_td );
1478 1479
}

Raymond Knopp's avatar
Raymond Knopp committed
1480
extern void    *te_thread (void *);
1481

Eurecom's avatar
Eurecom committed
1482
void init_te_thread(PHY_VARS_eNB *eNB) {
1483

1484
  L1_proc_t *proc = &eNB->proc;
1485

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1486 1487 1488
  for(int i=0; i<3 ;i++){
    proc->tep[i].eNB = eNB;
    proc->tep[i].instance_cnt_te         = -1;
1489
    
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1490 1491 1492
    pthread_mutex_init( &proc->tep[i].mutex_te, NULL);
    pthread_cond_init( &proc->tep[i].cond_te, NULL);
    pthread_attr_init( &proc->tep[i].attr_te);
1493
    
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1494
    LOG_I(PHY,"Creating te_thread %d\n",i);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1495 1496 1497 1498
    pthread_create(&proc->tep[i].pthread_te, &proc->tep[i].attr_te, te_thread, (void*)&proc->tep[i]);
  }
}
void kill_te_thread(PHY_VARS_eNB *eNB) {
1499

1500
  L1_proc_t *proc = &eNB->proc;
1501

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1502 1503 1504 1505
  for(int i=0; i<3 ;i++){
    proc->tep[i].instance_cnt_te         = 0;
    pthread_cond_signal(&proc->tep[i].cond_te);
    pthread_join(proc->tep[i].pthread_te, NULL);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1506 1507
    pthread_mutex_destroy( &proc->tep[i].mutex_te);
    pthread_cond_destroy( &proc->tep[i].cond_te);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1508
  }
1509 1510
}

1511
void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe) {
1512
  nfapi_rx_indication_pdu_t *pdu;
1513
  
Raymond Knopp's avatar
Raymond Knopp committed
1514 1515
  int             timing_advance_update;
  int             sync_pos;
1516
  
1517
  uint32_t        harq_pid;
1518
  
1519
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1520 1521 1522 1523 1524 1525 1526
  if (eNB->ulsch[UE_id]->ue_type > 0) harq_pid = 0;
  else
#endif
    {
      harq_pid = subframe2harq_pid (&eNB->frame_parms,
				    frame, subframe);
    }
1527
  
1528
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
1529
  
1530 1531
  eNB->UL_INFO.rx_ind.sfn_sf                    = frame<<4| subframe;
  eNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;
1532
  
1533
  pdu                                    = &eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus];
1534
  
1535
  //  pdu->rx_ue_information.handle          = eNB->ulsch[UE_id]->handle;
1536
  pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
1537
  pdu->rx_ue_information.rnti            = eNB->ulsch[UE_id]->rnti;
1538
  pdu->rx_indication_rel8.tl.tag         = NFAPI_RX_INDICATION_REL8_TAG;
1539
  pdu->rx_indication_rel8.length         = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3;
1540 1541
  pdu->rx_indication_rel8.offset         = 1;   // DJP - I dont understand - but broken unless 1 ????  0;  // filled in at the end of the UL_INFO formation
  pdu->data                              = eNB->ulsch[UE_id]->harq_processes[harq_pid]->b;  
1542 1543
  // estimate timing advance for MAC
  sync_pos                               = lte_est_timing_advance_pusch(eNB,UE_id);
Cedric Roux's avatar
Cedric Roux committed
1544
  timing_advance_update                  = sync_pos; // - eNB->frame_parms.nb_prefix_samples/4; //to check
1545

1546
  
1547 1548
  //  if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);}
  //  if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);}
1549
  switch (eNB->frame_parms.N_RB_DL) {
Raymond Knopp's avatar
Raymond Knopp committed
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
  case 6:                      /* nothing to do */
    break;
  case 15:
    timing_advance_update /= 2;
    break;
  case 25:
    timing_advance_update /= 4;
    break;
  case 50:
    timing_advance_update /= 8;
    break;
  case 75:
    timing_advance_update /= 12;
    break;
  case 100:
    timing_advance_update /= 16;
    break;
  default:
    abort ();
1569 1570
  }
  // put timing advance command in 0..63 range
Cedric Roux's avatar
Cedric Roux committed
1571
  timing_advance_update += 31;
Raymond Knopp's avatar
Raymond Knopp committed
1572 1573 1574 1575
  if (timing_advance_update < 0)
    timing_advance_update = 0;
  if (timing_advance_update > 63)
    timing_advance_update = 63;
Cedric Roux's avatar
Cedric Roux committed
1576
  pdu->rx_indication_rel8.timing_advance = timing_advance_update;
1577
  
1578
  // estimate UL_CQI for MAC (from antenna port 0 only)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1579
  int SNRtimes10 = dB_fixed_times10(eNB->pusch_vars[UE_id]->ulsch_power[0]) - 300;//(10*eNB->measurements.n0_power_dB[0]);
1580
  
1581

Raymond Knopp's avatar
Raymond Knopp committed
1582 1583 1584 1585 1586 1587
  if (SNRtimes10 < -640)
    pdu->rx_indication_rel8.ul_cqi = 0;
  else if (SNRtimes10 > 635)
    pdu->rx_indication_rel8.ul_cqi = 255;
  else
    pdu->rx_indication_rel8.ul_cqi = (640 + SNRtimes10) / 5;
1588
  
1589
  LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d), timing_advance %d (update %d)\n",
1590
		  harq_pid,frame,subframe,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,pdu->rx_indication_rel8.timing_advance,
1591
	timing_advance_update);
1592
  
1593 1594
  eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++;
  eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe;
1595 1596
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}
1597

1598
/* release the harq if its round is >= 'after_rounds' */
1599 1600
static void do_release_harq(PHY_VARS_eNB *eNB,int UE_id,int tb,uint16_t frame,uint8_t subframe,uint16_t mask, int after_rounds) {
  
1601 1602 1603
  LTE_eNB_DLSCH_t *dlsch0=NULL,*dlsch1=NULL;
  LTE_DL_eNB_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL;
  int harq_pid;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1604
  int subframe_tx,frame_tx;
1605
  int M,m;
Raymond Knopp's avatar
Raymond Knopp committed
1606 1607
  AssertFatal (UE_id != -1, "no existing dlsch context\n");
  AssertFatal (UE_id < NUMBER_OF_UE_MAX, "returned UE_id %d >= %d(NUMBER_OF_UE_MAX)\n", UE_id, NUMBER_OF_UE_MAX);
1608 1609
  dlsch0 = eNB->dlsch[UE_id][0];
  dlsch1 = eNB->dlsch[UE_id][1];
1610
  
1611 1612
  if (eNB->frame_parms.frame_type == FDD) {  
    subframe_tx = (subframe+6)%10;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1613 1614
    frame_tx = ul_ACK_subframe2_dl_frame(&eNB->frame_parms,frame,subframe,subframe_tx);
    harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx]; // or just use 0 for fdd?
1615
    
1616 1617 1618 1619
    AssertFatal((harq_pid>=0) && (harq_pid<10),"harq_pid %d not in 0...9\n",harq_pid);
    dlsch0_harq     = dlsch0->harq_processes[harq_pid];
    dlsch1_harq     = dlsch1->harq_processes[harq_pid];
    AssertFatal(dlsch0_harq!=NULL,"dlsch0_harq is null\n");
1620
    
Cedric Roux's avatar
Cedric Roux committed
1621 1622 1623
#if T_TRACER
    if (after_rounds != -1) {
      T(T_ENB_PHY_DLSCH_UE_NACK, T_INT(0), T_INT(frame), T_INT(subframe),
1624
	T_INT(dlsch0->rnti), T_INT(harq_pid));
Cedric Roux's avatar
Cedric Roux committed
1625 1626
    } else {
      T(T_ENB_PHY_DLSCH_UE_ACK, T_INT(0), T_INT(frame), T_INT(subframe),
1627
	T_INT(dlsch0->rnti), T_INT(harq_pid));
Cedric Roux's avatar
Cedric Roux committed
1628 1629
    }
#endif
1630
    
1631 1632 1633
    if (dlsch0_harq->round >= after_rounds) {
      dlsch0_harq->status = SCH_IDLE;
      /*if ((dlsch1_harq == NULL)||
1634 1635
	((dlsch1_harq!=NULL)&&
	(dlsch1_harq->status == SCH_IDLE)))*/
1636 1637
      dlsch0->harq_mask   &= ~(1<<harq_pid);
    }
1638
    LOG_D(PHY,"Frame %d, subframe %d: Releasing harq %d for UE %x\n",frame,subframe,harq_pid,dlsch0->rnti);
1639
    
1640 1641
  }
  else { // release all processes in the bundle that was acked, based on mask
Raymond Knopp's avatar
Raymond Knopp committed
1642
    // This is at most 4 for multiplexing and 9 for bundling/special bundling
1643
    M=ul_ACK_subframe2_M(&eNB->frame_parms,
1644 1645
			 subframe);
    
1646 1647 1648 1649
    for (m=0; m<M; m++) {
      subframe_tx = ul_ACK_subframe2_dl_subframe(&eNB->frame_parms,
						 subframe,
						 m);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1650
      frame_tx = ul_ACK_subframe2_dl_frame(&eNB->frame_parms,frame,subframe,subframe_tx);
1651
      if (((1<<m)&mask) > 0) {
1652
	harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1653
	if ((harq_pid>=0) && (harq_pid<dlsch0->Mdlharq)) {
1654 1655 1656
	  dlsch0_harq     = dlsch0->harq_processes[harq_pid];
	  dlsch1_harq     = dlsch1->harq_processes[harq_pid];
	  AssertFatal(dlsch0_harq!=NULL,"dlsch0_harq is null\n");
1657
	  
Cedric Roux's avatar
Cedric Roux committed
1658
#if T_TRACER
1659 1660 1661 1662 1663 1664 1665
	  if (after_rounds != -1) {
	    T(T_ENB_PHY_DLSCH_UE_NACK, T_INT(0), T_INT(frame), T_INT(subframe),
	      T_INT(dlsch0->rnti), T_INT(harq_pid));
	  } else {
	    T(T_ENB_PHY_DLSCH_UE_ACK, T_INT(0), T_INT(frame), T_INT(subframe),
	      T_INT(dlsch0->rnti), T_INT(harq_pid));
	  }
Cedric Roux's avatar
Cedric Roux committed
1666
#endif
1667
	  if (dlsch0_harq->round >= after_rounds) {
1668 1669
	    dlsch0_harq->status = SCH_IDLE;
	    if ((dlsch1_harq == NULL)||
1670 1671
		((dlsch1_harq!=NULL)&&
		 (dlsch1_harq->status == SCH_IDLE)))
1672
	      dlsch0->harq_mask   &= ~(1<<harq_pid);
1673
	  }
1674
	}
1675
	
1676
      }
1677
    }
1678
  } 
1679
}
1680

1681
static void release_harq(PHY_VARS_eNB *eNB,int UE_id,int tb,uint16_t frame,uint8_t subframe,uint16_t mask, int is_ack) {
1682 1683 1684 1685 1686 1687
  /* Maximum number of DL transmissions = 4.
   * TODO: get the value from configuration.
   * If is_ack is true then we release immediately. The value -1 can be used for that.
   */
  do_release_harq(eNB, UE_id, tb, frame, subframe, mask, is_ack ? -1 : 4);
}
Raymond Knopp's avatar
Raymond Knopp committed
1688

1689
int getM(PHY_VARS_eNB *eNB,int frame,int subframe) {
1690
  
1691 1692 1693 1694
  int M,Mtx=0;
  LTE_eNB_DLSCH_t *dlsch0=NULL,*dlsch1=NULL;
  LTE_DL_eNB_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL;
  int harq_pid;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1695
  int subframe_tx,frame_tx;
1696
  int m;
1697
  
1698 1699 1700 1701 1702 1703 1704
  M=ul_ACK_subframe2_M(&eNB->frame_parms,
		       subframe);
  
  for (m=0; m<M; m++) {
    subframe_tx = ul_ACK_subframe2_dl_subframe(&eNB->frame_parms,
					       subframe,
					       m);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1705
    frame_tx =  ul_ACK_subframe2_dl_frame(&eNB->frame_parms,frame,
frtabu's avatar
frtabu committed
1706 1707 1708 1709 1710 1711
                                          subframe,subframe_tx);
    if (dlsch0 == NULL || dlsch1 == NULL) {
        LOG_E(PHY, "dlsch0 and/or dlsch1 NULL, getM frame %i, subframe %i\n",frame,subframe);
	return Mtx;
    }

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1712
    harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];
1713
    
1714 1715 1716 1717 1718 1719
    if (harq_pid>=0 && harq_pid<10) {
      dlsch0_harq     = dlsch0->harq_processes[harq_pid];
      dlsch1_harq     = dlsch1->harq_processes[harq_pid];
      AssertFatal(dlsch0_harq!=NULL,"dlsch0_harq is null\n");
      if (dlsch0_harq->status == ACTIVE||
	  (dlsch1_harq!=NULL && dlsch1_harq->status == ACTIVE)) Mtx ++;
1720
    }
1721
  }
Raymond Knopp's avatar
Raymond Knopp committed
1722
  return (Mtx);
1723
}
1724 1725


1726 1727
void fill_ulsch_cqi_indication (PHY_VARS_eNB * eNB, uint16_t frame, uint8_t subframe, LTE_UL_eNB_HARQ_t * ulsch_harq, uint16_t rnti) {
  
Raymond Knopp's avatar
Raymond Knopp committed
1728 1729
  pthread_mutex_lock (&eNB->UL_INFO_mutex);
  nfapi_cqi_indication_pdu_t *pdu = &eNB->UL_INFO.cqi_ind.cqi_pdu_list[eNB->UL_INFO.cqi_ind.number_of_cqis];
1730
  nfapi_cqi_indication_raw_pdu_t *raw_pdu = &eNB->UL_INFO.cqi_ind.cqi_raw_pdu_list[eNB->UL_INFO.cqi_ind.number_of_cqis];
1731

1732
  pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
1733
  pdu->rx_ue_information.rnti = rnti;
Raymond Knopp's avatar
Raymond Knopp committed
1734 1735 1736 1737
  if (ulsch_harq->cqi_crc_status != 1)
    pdu->cqi_indication_rel9.data_offset = 0;
  else
    pdu->cqi_indication_rel9.data_offset = 1;   // fill in after all cqi_indications have been generated when non-zero
1738
  
1739 1740
  // by default set O to rank 1 value

1741
  pdu->cqi_indication_rel9.tl.tag = NFAPI_CQI_INDICATION_REL9_TAG;
Cedric Roux's avatar
Cedric Roux committed
1742
  pdu->cqi_indication_rel9.length = (ulsch_harq->Or1>>3) + ((ulsch_harq->Or1&7) > 0 ? 1 : 0);
1743 1744
  pdu->cqi_indication_rel9.ri[0]  = 0;
  // if we have RI bits, set them and if rank2 overwrite O
Raymond Knopp's avatar
Raymond Knopp committed
1745
  if (ulsch_harq->O_RI > 0) {
1746
    pdu->cqi_indication_rel9.ri[0] = ulsch_harq->o_RI[0];
Raymond Knopp's avatar
Raymond Knopp committed
1747 1748
    if (ulsch_harq->o_RI[0] == 2)
      pdu->cqi_indication_rel9.length = (ulsch_harq->Or2 >> 3) + ((ulsch_harq->Or2 & 7) > 0 ? 1 : 0);
1749 1750
    pdu->cqi_indication_rel9.timing_advance = 0;
  }
1751
  
1752
  pdu->cqi_indication_rel9.number_of_cc_reported = 1;
Raymond Knopp's avatar
Raymond Knopp committed
1753 1754
  pdu->ul_cqi_information.channel = 1;  // PUSCH
  memcpy ((void *) raw_pdu->pdu, ulsch_harq->o, pdu->cqi_indication_rel9.length);
1755
  eNB->UL_INFO.cqi_ind.number_of_cqis++;
1756
  LOG_D(PHY,"eNB->UL_INFO.cqi_ind.number_of_cqis:%d\n", eNB->UL_INFO.cqi_ind.number_of_cqis);
1757
  
1758
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
1759 1760
  
}							
1761

1762
void fill_ulsch_harq_indication (PHY_VARS_eNB * eNB, LTE_UL_eNB_HARQ_t * ulsch_harq, uint16_t rnti, int frame, int subframe, int bundling) {
1763

1764
  int UE_id = find_dlsch(rnti,eNB,SEARCH_EXIST);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1765 1766
  if( (UE_id<0) || (UE_id>=NUMBER_OF_UE_MAX) ){
    LOG_E(PHY,"illegal UE_id found!!! rnti %04x UE_id %d\n",rnti,UE_id);
1767
    return;
1768
  }
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1769
  //AssertFatal(UE_id>=0,"UE_id doesn't exist\n");
1770
  
1771
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
1772
  nfapi_harq_indication_pdu_t *pdu =   &eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list[eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs];
1773 1774
  int M;
  int i;
1775
  
1776 1777
  eNB->UL_INFO.harq_ind.header.message_id = NFAPI_HARQ_INDICATION;
  eNB->UL_INFO.harq_ind.sfn_sf = frame<<4|subframe;
1778
  
1779
  eNB->UL_INFO.harq_ind.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
1780
  
1781 1782
  pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
1783
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
1784
  pdu->rx_ue_information.rnti                         = rnti;
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824
  	    
  if (eNB->frame_parms.frame_type == FDD) {
    pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
    pdu->harq_indication_fdd_rel13.mode = 0;
    pdu->harq_indication_fdd_rel13.number_of_ack_nack = ulsch_harq->O_ACK;
    
    for (i = 0; i < ulsch_harq->O_ACK; i++) {
      AssertFatal (ulsch_harq->o_ACK[i] == 0 || ulsch_harq->o_ACK[i] == 1, "harq_ack[%d] is %d, should be 1,2 or 4\n", i, ulsch_harq->o_ACK[i]);
      
      pdu->harq_indication_fdd_rel13.harq_tb_n[i] = 2 - ulsch_harq->o_ACK[i];
      // release DLSCH if needed
      
      release_harq(eNB,UE_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
      
    }
  } else {                      // TDD
    M = ul_ACK_subframe2_M (&eNB->frame_parms, subframe);
    
    pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
    pdu->harq_indication_tdd_rel13.mode = 1-bundling;
    pdu->harq_indication_tdd_rel13.number_of_ack_nack = ulsch_harq->O_ACK;
    
    for (i = 0; i < ulsch_harq->O_ACK; i++) {
      AssertFatal (ulsch_harq->o_ACK[i] == 0 || ulsch_harq->o_ACK[i] == 1, "harq_ack[%d] is %d, should be 1,2 or 4\n", i, ulsch_harq->o_ACK[i]);
      
      pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 2-ulsch_harq->o_ACK[i];
      // release DLSCH if needed
      /* TODO: review this code, it's most certainly wrong.
       * We have to release the proper HARQ in case of ACK or NACK if max retransmission reached.
       * Basically, call release_harq with 1 as last argument when ACK and 0 when NACK.
       */
      release_harq(eNB,UE_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
      if      (M==1 && ulsch_harq->O_ACK==1 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,UE_id,0,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
      else if (M==1 && ulsch_harq->O_ACK==2 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,UE_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
      else if (M>1 && ulsch_harq->o_ACK[i] == 1) {
	// spatial bundling
	release_harq(eNB,UE_id,0,frame,subframe,1<<i, ulsch_harq->o_ACK[i] == 1);
	release_harq(eNB,UE_id,1,frame,subframe,1<<i, ulsch_harq->o_ACK[i] == 1);
      }
    }
Cedric Roux's avatar
Cedric Roux committed
1825 1826 1827 1828
  }

  //LOG_E(PHY,"eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs:%d\n", eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs);
  eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs++;
1829
    
Cedric Roux's avatar
Cedric Roux committed
1830
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
1831
    
1832
}
1833

1834
void fill_uci_harq_indication (PHY_VARS_eNB * eNB, LTE_eNB_UCI * uci, int frame, int subframe, uint8_t * harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) {
1835

Raymond Knopp's avatar
Raymond Knopp committed
1836
  int UE_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST);
1837 1838 1839 1840 1841
  //AssertFatal(UE_id>=0,"UE_id doesn't exist rnti:%x\n", uci->rnti);
  if (UE_id < 0) {
    LOG_E(PHY,"SFN/SF:%04d%d Unable to find rnti:%x do not send HARQ\n", frame, subframe, uci->rnti);
    return;
  }
1842
  
1843
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
1844
  
1845 1846 1847
  nfapi_harq_indication_t *ind       = &eNB->UL_INFO.harq_ind;
  nfapi_harq_indication_body_t *body = &ind->harq_indication_body;
  nfapi_harq_indication_pdu_t *pdu   = &body->harq_pdu_list[eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs];
1848
  
1849 1850
  ind->sfn_sf = frame<<4|subframe;
  ind->header.message_id = NFAPI_HARQ_INDICATION;
1851
  
1852
  body->tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
1853
  
1854 1855
  pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
1856
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
1857
  pdu->rx_ue_information.rnti                         = uci->rnti;
1858
  
1859
  // estimate UL_CQI for MAC (from antenna port 0 only)
1860
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1861
  int SNRtimes10 = dB_fixed_times10(uci->stat) - 300;//(10*eNB->measurements.n0_power_dB[0]);
1862
	    
Raymond Knopp's avatar
Raymond Knopp committed
1863 1864
  if (SNRtimes10 < -100)
    LOG_I (PHY, "uci->stat %d \n", uci->stat);
1865
  
Raymond Knopp's avatar
Raymond Knopp committed
1866 1867 1868 1869 1870 1871
  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;
1872
  pdu->ul_cqi_information.channel = 0;
1873
  
1874 1875
  if (eNB->frame_parms.frame_type == FDD) {
    if (uci->pucch_fmt == pucch_format1a) {
1876
      pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
1877 1878
      pdu->harq_indication_fdd_rel13.mode = 0;  
      pdu->harq_indication_fdd_rel13.number_of_ack_nack = 1;
1879
      
Raymond Knopp's avatar
Raymond Knopp committed
1880
      AssertFatal (harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n", harq_ack[0]);
1881 1882
      pdu->harq_indication_fdd_rel13.harq_tb_n[0] = harq_ack[0];
      // release DLSCH if needed
1883
      release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
1884 1885
    }
    else if (uci->pucch_fmt == pucch_format1b) {
1886
      pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
1887 1888
      pdu->harq_indication_fdd_rel13.mode = 0;  
      pdu->harq_indication_fdd_rel13.number_of_ack_nack = 2;
Raymond Knopp's avatar
Raymond Knopp committed
1889 1890
      AssertFatal (harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n", harq_ack[0]);
      AssertFatal (harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n", harq_ack[1]);
1891
      pdu->harq_indication_fdd_rel13.harq_tb_n[0] = harq_ack[0];
Raymond Knopp's avatar
Raymond Knopp committed
1892
      pdu->harq_indication_fdd_rel13.harq_tb_n[1] = harq_ack[1];
1893
      // release DLSCH if needed
1894 1895
      release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
      release_harq(eNB,UE_id,1,frame,subframe,0xffff, harq_ack[1] == 1);
1896 1897 1898 1899
    }
    else AssertFatal(1==0,"only format 1a/b for now, received %d\n",uci->pucch_fmt); 
  }
  else { // TDD
Raymond Knopp's avatar
Raymond Knopp committed
1900
    AssertFatal (tdd_mapping_mode == 0 || tdd_mapping_mode == 1 || tdd_mapping_mode == 2, "Illegal tdd_mapping_mode %d\n", tdd_mapping_mode);
1901
    pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
1902
    pdu->harq_indication_tdd_rel13.mode = tdd_mapping_mode;  
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1903
    LOG_D(PHY,"%s(eNB, uci_harq format %d, rnti:%04x, frame:%d, subframe:%d, tdd_mapping_mode:%d) harq_ack[0]:%d harq_ack[1]:%d\n", __FUNCTION__, uci->pucch_fmt,uci->rnti, frame, subframe, tdd_mapping_mode,harq_ack[0],harq_ack[1]);
1904
    switch (tdd_mapping_mode) {
Raymond Knopp's avatar
Raymond Knopp committed
1905
    case 0:                    // bundling
1906
      
1907
      if (uci->pucch_fmt == pucch_format1a) {
1908
	pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
1909
	pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1;	
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1910
	LOG_D(PHY,"bundling, pucch1a, number of ack nack %d\n",pdu->harq_indication_tdd_rel13.number_of_ack_nack);
1911 1912 1913
	AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n",harq_ack[0]);
	pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = harq_ack[0];
	// release all bundled DLSCH if needed
1914
	release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
1915 1916 1917 1918 1919
      }
      else if (uci->pucch_fmt == pucch_format1b) {
	pdu->harq_indication_tdd_rel13.number_of_ack_nack = 2;
	AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n",harq_ack[0]);
	AssertFatal(harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n",harq_ack[1]);
1920
	pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
1921 1922 1923
	pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = harq_ack[0];
	pdu->harq_indication_tdd_rel13.harq_data[1].bundling.value_0 = harq_ack[1]; 
	// release all DLSCH if needed
1924 1925
	release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
	release_harq(eNB,UE_id,1,frame,subframe,0xffff, harq_ack[1] == 1);
1926 1927
      }
      break;
Raymond Knopp's avatar
Raymond Knopp committed
1928 1929
    case 1:                    // multiplexing
      AssertFatal (uci->pucch_fmt == pucch_format1b, "uci->pucch_format %d is not format1b\n", uci->pucch_fmt);
1930
      
1931
      if (uci->num_pucch_resources == 1 && uci->pucch_fmt == pucch_format1a) {
1932
	pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
1933 1934 1935 1936
	pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1;	
	AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n",harq_ack[0]);
	pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0];
	// release all DLSCH if needed
1937
	release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
1938
      }
1939
      else if (uci->num_pucch_resources == 1 && uci->pucch_fmt == pucch_format1b) {
1940
	pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
1941 1942 1943 1944 1945 1946
	pdu->harq_indication_tdd_rel13.number_of_ack_nack = 2;
	AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n",harq_ack[0]);
	AssertFatal(harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n",harq_ack[1]);
	pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0];
	pdu->harq_indication_tdd_rel13.harq_data[1].multiplex.value_0 = harq_ack[1]; 
	// release all DLSCH if needed
1947 1948
	release_harq(eNB,UE_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
	release_harq(eNB,UE_id,1,frame,subframe,0xffff, harq_ack[1] == 1);
1949 1950
      }
      else { // num_pucch_resources (M) > 1
1951
	pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
1952
	pdu->harq_indication_tdd_rel13.number_of_ack_nack = uci->num_pucch_resources;
1953
	
1954 1955 1956 1957 1958
	pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0];
	pdu->harq_indication_tdd_rel13.harq_data[1].multiplex.value_0 = harq_ack[1];
	if (uci->num_pucch_resources == 3) 	pdu->harq_indication_tdd_rel13.harq_data[2].multiplex.value_0 = harq_ack[2];
	if (uci->num_pucch_resources == 4) 	pdu->harq_indication_tdd_rel13.harq_data[3].multiplex.value_0 = harq_ack[3];
	// spatial-bundling in this case so release both HARQ if necessary
1959 1960
	release_harq(eNB,UE_id,0,frame,subframe,tdd_multiplexing_mask, 1 /* force release? previous code was unconditional */);
	release_harq(eNB,UE_id,1,frame,subframe,tdd_multiplexing_mask, 1 /* force release? previous code was unconditional */);
1961 1962 1963
      }
      break;
    case 2: // special bundling (SR collision)
1964
      pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
1965
      pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1966
      pdu->harq_indication_tdd_rel13.mode = 0;
1967 1968
      int tdd_config5_sf2scheds=0;
      if (eNB->frame_parms.tdd_config==5) tdd_config5_sf2scheds = getM(eNB,frame,subframe);
1969
      
1970 1971
      switch (harq_ack[0]) {
      case 0:
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1972
      case 4:
1973 1974
	pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0;
	/* TODO: release_harq here? this whole code looks suspicious */
1975 1976 1977 1978
	break;
      case 1: // check if M=1,4,7
	if (uci->num_pucch_resources == 1 || uci->num_pucch_resources == 4 ||
	    tdd_config5_sf2scheds == 1 || tdd_config5_sf2scheds == 4 || tdd_config5_sf2scheds == 7) {
1979
	  pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1;
1980 1981
	  release_harq(eNB,UE_id,0,frame,subframe,0xffff, 1);
	  release_harq(eNB,UE_id,1,frame,subframe,0xffff, 1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1982
	}else{
1983
	  pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0;
1984
	}
1985 1986 1987 1988
	break;
      case 2: // check if M=2,5,8
	if (uci->num_pucch_resources == 2 || tdd_config5_sf2scheds == 2 || 
	    tdd_config5_sf2scheds == 5 || tdd_config5_sf2scheds == 8) {
1989
	  pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1;
1990 1991
	  release_harq(eNB,UE_id,0,frame,subframe,0xffff, 1);
	  release_harq(eNB,UE_id,1,frame,subframe,0xffff, 1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1992
	}else{
1993
	  pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0;
1994 1995 1996 1997 1998
	}
	break;
      case 3: // check if M=3,6,9
	if (uci->num_pucch_resources == 3 || tdd_config5_sf2scheds == 3 || 
	    tdd_config5_sf2scheds == 6 || tdd_config5_sf2scheds == 9) {
1999
	  pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1;
2000 2001
	  release_harq(eNB,UE_id,0,frame,subframe,0xffff, 1);
	  release_harq(eNB,UE_id,1,frame,subframe,0xffff, 1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
2002
	}else{
2003
	  pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0;
2004 2005 2006 2007
	}
	break;
      }
      break;
2008
      
2009
    }
Raymond Knopp's avatar
Raymond Knopp committed
2010
  }                             //TDD
2011 2012
  
  
2013 2014
  eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs++;
  LOG_D(PHY,"Incremented eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs:%d\n", eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs);
2015 2016
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);  
}
2017

2018
void fill_crc_indication (PHY_VARS_eNB * eNB, int UE_id, int frame, int subframe, uint8_t crc_flag) {
2019

2020
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
2021
  nfapi_crc_indication_pdu_t *pdu =   &eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list[eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs];
2022
  
2023 2024 2025
  eNB->UL_INFO.crc_ind.sfn_sf                         = frame<<4 | subframe;
  eNB->UL_INFO.crc_ind.header.message_id              = NFAPI_CRC_INDICATION;
  eNB->UL_INFO.crc_ind.crc_indication_body.tl.tag     = NFAPI_CRC_INDICATION_BODY_TAG;
2026

Raymond Knopp's avatar
Raymond Knopp committed
2027
  pdu->instance_length = 0;     // don't know what to do with this
2028
  //  pdu->rx_ue_information.handle                       = handle;
2029

2030
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
2031
  pdu->rx_ue_information.rnti                         = eNB->ulsch[UE_id]->rnti;
Cedric Roux's avatar
Cedric Roux committed
2032
  pdu->crc_indication_rel8.tl.tag                     = NFAPI_CRC_INDICATION_REL8_TAG;
2033
  pdu->crc_indication_rel8.crc_flag                   = crc_flag;
2034
  
2035
  eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs++;
2036
  
2037
  //LOG_D(PHY, "%s() rnti:%04x crcs:%d crc_flag:%d\n", __FUNCTION__, pdu->rx_ue_information.rnti, eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs, crc_flag);
2038
  
2039 2040
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}
2041

2042
void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc)
2043 2044
{
  //RX processing for ue-specific resources (i
Raymond Knopp's avatar
Raymond Knopp committed
2045 2046 2047
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  const int       subframe = proc->subframe_rx;
  const int       frame = proc->frame_rx;
2048
  
Cedric Roux's avatar
Cedric Roux committed
2049
  /* TODO: use correct rxdata */
Raymond Knopp's avatar
Raymond Knopp committed
2050 2051
  T (T_ENB_PHY_INPUT_SIGNAL, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (0),
     T_BUFFER (&eNB->RU_list[0]->common.rxdata[0][subframe * eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti * 4));
2052
  
Cedric Roux's avatar
Cedric Roux committed
2053
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return;
2054
  
Cedric Roux's avatar
Cedric Roux committed
2055
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
2056
  
2057
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 );
2058

Raymond Knopp's avatar
Raymond Knopp committed
2059
  LOG_D (PHY, "[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n", eNB->Mod_id, frame, subframe);
2060
  
Raymond Knopp's avatar
Raymond Knopp committed
2061 2062 2063 2064
  eNB->rb_mask_ul[0] = 0;
  eNB->rb_mask_ul[1] = 0;
  eNB->rb_mask_ul[2] = 0;
  eNB->rb_mask_ul[3] = 0;
2065
  
Raymond Knopp's avatar
Raymond Knopp committed
2066
  // Fix me here, these should be locked
Cedric Roux's avatar
Cedric Roux committed
2067 2068
  eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus  = 0;
  eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2069
  // Call SRS first since all others depend on presence of SRS or lack thereof
Raymond Knopp's avatar
Raymond Knopp committed
2070
  srs_procedures (eNB, proc);
2071
  
2072
  eNB->first_run_I0_measurements = 0;
2073
  
Raymond Knopp's avatar
Raymond Knopp committed
2074
  uci_procedures (eNB, proc);
2075
  
2076 2077 2078
  if (nfapi_mode == 0 || nfapi_mode == 1) { // If PNF or monolithic
    pusch_procedures(eNB,proc);
  }
2079

Raymond Knopp's avatar
Raymond Knopp committed
2080
  lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements);
2081

2082
  int min_I0=1000,max_I0=0;
2083
  if ((frame==0) && (subframe==4)) { 
2084 2085
    for (int i=0;i<eNB->frame_parms.N_RB_UL;i++) {
      if (i==(eNB->frame_parms.N_RB_UL>>1) - 1) i+=2;
2086
      
2087 2088
      if (eNB->measurements.n0_subband_power_tot_dB[i]<min_I0) min_I0 = eNB->measurements.n0_subband_power_tot_dB[i];
      if (eNB->measurements.n0_subband_power_tot_dB[i]>max_I0) max_I0 = eNB->measurements.n0_subband_power_tot_dB[i];
2089
      
2090
    }
Raymond Knopp's avatar
Raymond Knopp committed
2091
    LOG_I (PHY, "max_I0 %d, min_I0 %d\n", max_I0, min_I0);
2092
  }
2093
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 );
Raymond Knopp's avatar
Raymond Knopp committed
2094
}