phy_procedures_lte_eNb.c 116 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22 23

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

#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"

38
#include "PHY/LTE_TRANSPORT/if4_tools.h"
Sandeep Kumar's avatar
Sandeep Kumar committed
39
#include "PHY/LTE_TRANSPORT/if5_tools.h"
40

41 42 43 44
#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif

45
//#define DEBUG_PHY_PROC (Already defined in cmake)
46 47 48 49 50 51 52
//#define DEBUG_ULSCH

#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/defs.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

53 54
#include "T.h"

55
#include "assertions.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
56
#include "msc.h"
57

58 59
#include <time.h>

60
#if defined(ENABLE_ITTI)
Lionel Gauthier's avatar
Lionel Gauthier committed
61
#   include "intertask_interface.h"
62 63
#endif

64

65
#if defined(FLEXRAN_AGENT_SB_IF)
66
//Agent-related headers
67
#include "ENB_APP/flexran_agent_extern.h"
68
#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
69
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
70
#endif
71

72 73 74 75 76 77
//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

78 79
void exit_fun(const char* s);

80 81
extern int exit_openair;

82 83
// Fix per CC openair rf/if device update
// extern openair0_device openair0;
84

85 86 87
unsigned char dlsch_input_buffer[2700] __attribute__ ((aligned(32)));
int eNB_sync_buffer0[640*6] __attribute__ ((aligned(32)));
int eNB_sync_buffer1[640*6] __attribute__ ((aligned(32)));
88 89
int *eNB_sync_buffer[2] = {eNB_sync_buffer0, eNB_sync_buffer1};

90
extern uint16_t hundred_times_log10_NPRB[100];
91

92
unsigned int max_peak_val;
93
int max_sync_pos;
94

95 96 97
int harq_pid_updated[NUMBER_OF_UE_MAX][8] = {{0}};
int harq_pid_round[NUMBER_OF_UE_MAX][8] = {{0}};

98 99 100 101 102 103
//DCI_ALLOC_t dci_alloc[8];

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

104
#if defined(SMBV) 
105 106
extern const char smbv_fname[];
extern unsigned short config_frames[4];
107
extern uint8_t smbv_frame_cnt;
108 109 110 111 112 113
#endif

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

114
uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id)
115
{
Raymond Knopp's avatar
 
Raymond Knopp committed
116

117 118
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
119

120
  LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking for SR TXOp(sr_ConfigIndex %d)\n",
121 122
        eNB->Mod_id,eNB->ulsch[UE_id]->rnti,frame,subframe,
        eNB->scheduling_request_config[UE_id].sr_ConfigIndex);
123

124 125
  if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 4) {        // 5 ms SR period
    if ((subframe%5) == eNB->scheduling_request_config[UE_id].sr_ConfigIndex)
126
      return(1);
127 128
  } else if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 14) { // 10 ms SR period
    if (subframe==(eNB->scheduling_request_config[UE_id].sr_ConfigIndex-5))
129
      return(1);
130 131
  } else if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 34) { // 20 ms SR period
    if ((10*(frame&1)+subframe) == (eNB->scheduling_request_config[UE_id].sr_ConfigIndex-15))
132
      return(1);
133 134
  } else if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 74) { // 40 ms SR period
    if ((10*(frame&3)+subframe) == (eNB->scheduling_request_config[UE_id].sr_ConfigIndex-35))
135
      return(1);
136 137
  } else if (eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 154) { // 80 ms SR period
    if ((10*(frame&7)+subframe) == (eNB->scheduling_request_config[UE_id].sr_ConfigIndex-75))
138
      return(1);
139 140 141 142
  }

  return(0);
}
143

144

145
int32_t add_ue(int16_t rnti, PHY_VARS_eNB *eNB)
146
{
147
  uint8_t i;
148

149 150

  LOG_D(PHY,"[eNB %d/%d] Adding UE with rnti %x\n",
151 152
        eNB->Mod_id,
        eNB->CC_id,
153
        (uint16_t)rnti);
154 155

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
156
    if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) {
157
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed add ue %"PRIx16" (ENOMEM)", rnti);
158 159
      LOG_E(PHY,"Can't add UE, not enough memory allocated\n");
      return(-1);
160
    } else {
161
      if (eNB->UE_stats[i].crnti==0) {
162
        MSC_LOG_EVENT(MSC_PHY_ENB, "0 Add ue %"PRIx16" ", rnti);
163
        LOG_D(PHY,"UE_id %d associated with rnti %x\n",i, (uint16_t)rnti);
164 165 166
        eNB->dlsch[i][0]->rnti = rnti;
        eNB->ulsch[i]->rnti = rnti;
        eNB->UE_stats[i].crnti = rnti;
167

168 169 170
	eNB->UE_stats[i].Po_PUCCH1_below = 0;
	eNB->UE_stats[i].Po_PUCCH1_above = (int32_t)pow(10.0,.1*(eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH+eNB->rx_total_gain_dB));
	eNB->UE_stats[i].Po_PUCCH        = (int32_t)pow(10.0,.1*(eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH+eNB->rx_total_gain_dB));
171
	LOG_D(PHY,"Initializing Po_PUCCH: p0_NominalPUCCH %d, gain %d => %d\n",
172 173 174
	      eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH,
	      eNB->rx_total_gain_dB,
	      eNB->UE_stats[i].Po_PUCCH);
175
  
176
        return(i);
177
      }
178
    }
179 180 181 182
  }
  return(-1);
}

183
int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) {
184
  uint8_t i;
185
  int CC_id;
186
  PHY_VARS_eNB *eNB;
187 188

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
189
    eNB = PHY_vars_eNB_g[Mod_idP][CC_id];
190
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
191
      if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) {
192 193 194 195
	MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (ENOMEM)", rnti);
	LOG_E(PHY,"Can't remove UE, not enough memory allocated\n");
	return(-1);
      } else {
196
	if (eNB->UE_stats[i].crnti==rntiP) {
197
	  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Removed ue %"PRIx16" ", rntiP);
198 199 200

	  LOG_D(PHY,"eNB %d removing UE %d with rnti %x\n",eNB->Mod_id,i,rntiP);

201
	  //LOG_D(PHY,("[PHY] UE_id %d\n",i);
202 203 204 205
	  clean_eNb_dlsch(eNB->dlsch[i][0]);
	  clean_eNb_ulsch(eNB->ulsch[i]);
	  //eNB->UE_stats[i].crnti = 0;
	  memset(&eNB->UE_stats[i],0,sizeof(LTE_eNB_UE_stats));
206 207
	  //  mac_exit_wrapper("Removing UE");
	  
208

209 210
	  return(i);
	}
211
      }
212
    }
213
  }
214
  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (not found)", rntiP);
215 216 217
  return(-1);
}

218
int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
219
{
220
  uint8_t i;
221

222
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
223 224
    if (eNB->UE_stats[i].crnti==0) {
      /*if ((eNB->dlsch[i]) &&
225 226
	(eNB->dlsch[i][0]) &&
	(eNB->dlsch[i][0]->rnti==0))*/
227 228 229
      LOG_D(PHY,"Next free UE id is %d\n",i);
      return(i);
    }
230
  }
231

232 233 234
  return(-1);
}

235
int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t harq_flag)
236 237 238 239
{
  LTE_eNB_DLSCH_t *DLSCH_ptr;
  LTE_eNB_ULSCH_t *ULSCH_ptr;
  uint8_t ulsch_subframe,ulsch_frame;
240
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
241
  int8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]);
242 243

  if (UE_id==-1) {
244
    LOG_D(PHY,"Cannot find UE with rnti %x (Mod_id %d, CC_id %d)\n",rnti, Mod_id, CC_id);
245 246
    *round=0;
    return(-1);
247 248
  }

249 250
  if ((harq_flag == openair_harq_DL) || (harq_flag == openair_harq_RA))  {// this is a DL request

251
    DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[(uint32_t)UE_id][0];
252

253 254 255 256 257 258 259 260 261 262
    if (harq_flag == openair_harq_RA) {
      if (DLSCH_ptr->harq_processes[0] != NULL) {
	*harq_pid = 0;
	*round = DLSCH_ptr->harq_processes[0]->round;
	return 0;
      } else {
	return -1;
      }
    }

263 264
    /* let's go synchronous for the moment - maybe we can change at some point */
    i = (frame * 10 + subframe) % 8;
265

266 267 268 269 270
    if (DLSCH_ptr->harq_processes[i]->status == ACTIVE) {
      *harq_pid = i;
      *round = DLSCH_ptr->harq_processes[i]->round;
    } else if (DLSCH_ptr->harq_processes[i]->status == SCH_IDLE) {
      *harq_pid = i;
271
      *round = 0;
272 273 274
    } else {
      printf("%s:%d: bad state for harq process - PLEASE REPORT!!\n", __FILE__, __LINE__);
      abort();
275
    }
276
  } else { // This is a UL request
277

278 279 280
    ULSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->ulsch[(uint32_t)UE_id];
    ulsch_subframe = pdcch_alloc2ul_subframe(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,subframe);
    ulsch_frame    = pdcch_alloc2ul_frame(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,frame,subframe);
281
    // Note this is for TDD configuration 3,4,5 only
282
    *harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,
283 284
                                  ulsch_frame,
                                  ulsch_subframe);
285
    *round    = ULSCH_ptr->harq_processes[*harq_pid]->round;
286
    LOG_T(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Checking HARQ, round %d\n",Mod_id,*harq_pid,frame,subframe,*round);
287
  }
288

289 290 291
  return(0);
}

292
int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
293
{
294
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
295 296
}

297 298
int16_t get_target_pucch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
{
299
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
300 301
}

302
#ifdef EMOS
303
void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB)
304
{
305 306 307 308

}
#endif

309

310

311
void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type)
312 313
{
  UNUSED(r_type);
314
  int subframe = proc->subframe_rx;
315

316
#ifdef DEBUG_PHY_PROC
317
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", eNB->Mod_id,proc->frame_rx, subframe);
318
#endif
319

320

321
  if (eNB->abstraction_flag == 0) {
322
    lte_eNB_I0_measurements(eNB,
323
			    subframe,
324
                            0,
325
                            eNB->first_run_I0_measurements);
Raymond Knopp's avatar
 
Raymond Knopp committed
326
  }
327

328
#ifdef PHY_ABSTRACTION
Raymond Knopp's avatar
 
Raymond Knopp committed
329
  else {
330
    lte_eNB_I0_measurements_emul(eNB,
331
                                 0);
332
  }
333

Raymond Knopp's avatar
 
Raymond Knopp committed
334 335
#endif

336

337 338
}

Raymond Knopp's avatar
 
Raymond Knopp committed
339 340


341
#ifdef EMOS
342
void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *eNB)
343 344
{

345 346
  uint8_t aa;
  uint16_t last_subframe_emos;
347
  uint16_t pilot_pos1 = 3 - eNB->frame_parms.Ncp, pilot_pos2 = 10 - 2*eNB->frame_parms.Ncp;
348
  uint32_t bytes;
349 350 351

  last_subframe_emos=0;

Raymond Knopp's avatar
 
Raymond Knopp committed
352

Raymond Knopp's avatar
 
Raymond Knopp committed
353

Raymond Knopp's avatar
 
Raymond Knopp committed
354

355
#ifdef EMOS_CHANNEL
356

357
  //if (last_slot%2==1) // this is for all UL subframes
358
  if (subframe==3)
359 360 361 362 363 364 365
    for (aa=0; aa<eNB->frame_parms.nb_antennas_rx; aa++) {
      memcpy(&emos_dump_eNB.channel[aa][last_subframe_emos*2*eNB->frame_parms.N_RB_UL*12],
             &eNB->pusch_vars[0]->drs_ch_estimates[0][aa][eNB->frame_parms.N_RB_UL*12*pilot_pos1],
             eNB->frame_parms.N_RB_UL*12*sizeof(int));
      memcpy(&emos_dump_eNB.channel[aa][(last_subframe_emos*2+1)*eNB->frame_parms.N_RB_UL*12],
             &eNB->pusch_vars[0]->drs_ch_estimates[0][aa][eNB->frame_parms.N_RB_UL*12*pilot_pos2],
             eNB->frame_parms.N_RB_UL*12*sizeof(int));
366
    }
367

368 369
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
370
  if (subframe==4) {
371
    emos_dump_eNB.timestamp = rt_get_time_ns();
372 373 374 375 376
    emos_dump_eNB.frame_tx = eNB->proc[subframe].frame_rx;
    emos_dump_eNB.rx_total_gain_dB = eNB->rx_total_gain_dB;
    emos_dump_eNB.mimo_mode = eNB->transmission_mode[0];
    memcpy(&emos_dump_eNB.measurements,
           &eNB->measurements[0],
377
           sizeof(PHY_MEASUREMENTS_eNB));
378
    memcpy(&emos_dump_eNB.UE_stats[0],&eNB->UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats));
379 380

    bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, &emos_dump_eNB, sizeof(fifo_dump_emos_eNB));
381

382 383
    //bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, "test", sizeof("test"));
    if (bytes!=sizeof(fifo_dump_emos_eNB)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
384
      LOG_W(PHY,"[eNB %d] Frame %d, subframe %d, Problem writing EMOS data to FIFO (bytes=%d, size=%d)\n",
385
            eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, subframe,bytes,sizeof(fifo_dump_emos_eNB));
386
    } else {
387
      if (eNB->proc[(subframe+1)%10].frame_tx%100==0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
388
        LOG_I(PHY,"[eNB %d] Frame %d (%d), subframe %d, Writing %d bytes EMOS data to FIFO\n",
389
              eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, ((fifo_dump_emos_eNB*)&emos_dump_eNB)->frame_tx, subframe, bytes);
390
      }
391
    }
392 393 394 395 396 397 398
  }
}
#endif


#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
#define AMP_OVER_2 (AMP>>1)
399 400
int QPSK[4]= {AMP_OVER_SQRT2|(AMP_OVER_SQRT2<<16),AMP_OVER_SQRT2|((65536-AMP_OVER_SQRT2)<<16),((65536-AMP_OVER_SQRT2)<<16)|AMP_OVER_SQRT2,((65536-AMP_OVER_SQRT2)<<16)|(65536-AMP_OVER_SQRT2)};
int QPSK2[4]= {AMP_OVER_2|(AMP_OVER_2<<16),AMP_OVER_2|((65536-AMP_OVER_2)<<16),((65536-AMP_OVER_2)<<16)|AMP_OVER_2,((65536-AMP_OVER_2)<<16)|(65536-AMP_OVER_2)};
401

Lionel Gauthier's avatar
Lionel Gauthier committed
402

Raymond Knopp's avatar
 
Raymond Knopp committed
403

Cedric Roux's avatar
Cedric Roux committed
404
unsigned int taus(void);
405
DCI_PDU DCI_pdu_tmp;
Raymond Knopp's avatar
 
Raymond Knopp committed
406

407

408
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,relaying_type_t r_type) {
409 410


411
#ifdef Rel10
412 413
  MCH_PDU *mch_pduP;
  MCH_PDU  mch_pdu;
414
  //  uint8_t sync_area=255;
415
#endif
416

417
  int subframe = proc->subframe_tx;
418

419
  if (eNB->abstraction_flag==0) {
420 421
    // This is DL-Cell spec pilots in Control region
    generate_pilots_slot(eNB,
422
			 eNB->common_vars.txdataF[0],
423 424
			 AMP,
			 subframe<<1,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
425
  }
426
  
427
#ifdef Rel10
428 429 430 431
  // 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
  mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id,
				    eNB->CC_id,
432
				    proc->frame_tx,
433 434 435 436 437 438
				    subframe);
  
  switch (r_type) {
  case no_relay:
    if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0
      LOG_I(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n",
439 440
	    eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs,
	    eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
441 442
    else {
      LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n",
443
	    eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->sync_area,
444 445
	    (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment");
      mch_pduP = NULL;
Lionel Gauthier's avatar
Lionel Gauthier committed
446
    }
447
    
Raymond Knopp's avatar
 
Raymond Knopp committed
448
    break;
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
    
  case multicast_relay:
    if ((mch_pduP->Pdu_size > 0) && ((mch_pduP->mcch_active == 1) || mch_pduP->msi_active==1)) {
      LOG_I(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Got the MCH PDU for MBSFN  sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n",
	    rn->Mod_id,rn->frame, subframe,
	    mch_pduP->sync_area,mch_pduP->mcs,mch_pduP->Pdu_size);
    } else if (rn->mch_avtive[subframe%5] == 1) { // SF2 -> SF7, SF3 -> SF8
      mch_pduP= &mch_pdu;
      memcpy(&mch_pduP->payload, // could be a simple copy
	     rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->b,
	     rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3);
      mch_pduP->Pdu_size = (uint16_t) (rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3);
      mch_pduP->mcs = rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->mcs;
      LOG_I(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Forward the MCH PDU for MBSFN received on SF %d sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n",
	    rn->Mod_id,rn->frame, subframe,subframe%5,
	    rn->sync_area[subframe%5],mch_pduP->mcs,mch_pduP->Pdu_size);
Raymond Knopp's avatar
 
Raymond Knopp committed
465
    } else {
466
      mch_pduP=NULL;
Raymond Knopp's avatar
 
Raymond Knopp committed
467
    }
468 469
    
    rn->mch_avtive[subframe]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
470
    break;
471
    
472
  default:
473
    LOG_W(PHY,"[eNB %"PRIu8"] Frame %d subframe %d: unknown relaying type %d \n",
474
	  eNB->Mod_id,proc->frame_tx,subframe,r_type);
475 476 477 478 479
    mch_pduP=NULL;
    break;
  }// switch
  
  if (mch_pduP) {
480
    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0);
481
    // Generate PMCH
482
    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload);
483
  } else {
484
    LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
485
  }
486
  
487
#endif
488
}
489

490
void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
491

492 493
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int **txdataF = eNB->common_vars.txdataF[0];
494
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
495 496
  int subframe = proc->subframe_tx;
  int frame = proc->frame_tx;
497

498
  // generate Cell-Specific Reference Signals for both slots
499
  if (eNB->abstraction_flag==0) {
500 501 502 503 504 505 506 507 508 509 510 511 512 513
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
			 subframe<<1,0);
    // check that 2nd slot is for DL
    if (subframe_select(fp,subframe) == SF_DL)
      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);
  }    
514

515
  // First half of PSS/SSS (FDD, slot 0)
Raymond Knopp's avatar
 
Raymond Knopp committed
516
  if (subframe == 0) {
517
    if ((fp->frame_type == FDD) &&
518
	(eNB->abstraction_flag==0)) {
519 520 521 522 523 524 525 526 527 528 529
      generate_pss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   0);
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 5 : 4,
		   0);
      
530
    }
531
    
532
    // generate PBCH (Physical Broadcast CHannel) info
533
    if ((frame&3) == 0) {
534
      pbch_pdu[2] = 0;
535
      
536
      // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators
537
      switch (fp->N_RB_DL) {
Raymond Knopp's avatar
 
Raymond Knopp committed
538
      case 6:
539 540
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (0<<5);
	break;
541
	
Raymond Knopp's avatar
 
Raymond Knopp committed
542
      case 15:
543 544 545
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (1<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
546
      case 25:
547 548 549
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
550
      case 50:
551 552 553
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (3<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
554
      case 75:
555 556 557
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (4<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
558
      case 100:
559 560 561
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (5<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
562
      default:
563 564 565
	// FIXME if we get here, this should be flagged as an error, right?
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
	break;
Raymond Knopp's avatar
 
Raymond Knopp committed
566
      }
567
      
568
      pbch_pdu[2] = (pbch_pdu[2]&0xef) |
569 570 571
	((fp->phich_config_common.phich_duration << 4)&0x10);
      
      switch (fp->phich_config_common.phich_resource) {
Raymond Knopp's avatar
 
Raymond Knopp committed
572
      case oneSixth:
573 574 575
	pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (0<<2);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
576
      case half:
577 578 579
	pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (1<<2);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
580
      case one:
581 582 583
	pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (2<<2);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
584
      case two:
585 586 587
	pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (3<<2);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
588
      default:
589 590
	// unreachable
	break;
Raymond Knopp's avatar
 
Raymond Knopp committed
591
      }
592
      
593 594
      pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((frame>>8)&0x3);
      pbch_pdu[1] = frame&0xfc;
595
      pbch_pdu[0] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
596
    }
597 598 599 600
      
    /// First half of SSS (TDD, slot 1)
    
    if ((fp->frame_type == TDD)&&
601
	(eNB->abstraction_flag==0)){
602 603 604 605 606 607
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   1);
    }
608

609
    /// generate PBCH
610
    if (eNB->abstraction_flag==0) {
611
      generate_pbch(&eNB->pbch,
612 613 614 615
                    txdataF,
                    AMP,
                    fp,
                    pbch_pdu,
616
                    frame&3);
617
    }
618 619 620
#ifdef PHY_ABSTRACTION
    else {
      generate_pbch_emul(eNB,pbch_pdu);
621
    }
622
#endif
623

624
  }
625 626
  else if ((subframe == 1) &&
	   (fp->frame_type == TDD)&&
627
	   (eNB->abstraction_flag==0)) {
628 629 630 631 632
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
633
  }
634 635 636 637
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
	   (fp->frame_type == FDD) &&
638
	   (eNB->abstraction_flag==0)) {
639 640 641 642 643 644 645 646 647 648
    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);
649

650
  }
651

652 653 654
  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
	   (fp->frame_type == TDD) &&
655
	   (eNB->abstraction_flag==0)) {
656 657 658 659 660
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
Raymond Knopp's avatar
 
Raymond Knopp committed
661
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
662

663 664 665
  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
	   (fp->frame_type == TDD) &&
666
	   (eNB->abstraction_flag==0)) {
667 668 669 670 671 672
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
673

674
}
Raymond Knopp's avatar
 
Raymond Knopp committed
675

676
void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,const int UE_id) {
677

678
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
679 680
  int frame = proc->frame_tx;
  int subframe = proc->subframe_tx;
681 682 683 684 685 686 687 688 689

  // if we have SI_RNTI, configure dlsch parameters and CCE index
  if (dci_alloc->rnti == SI_RNTI) {
    LOG_D(PHY,"Generating dlsch params for SI_RNTI\n");
    generate_eNB_dlsch_params_from_dci(frame,
				       subframe,
				       &dci_alloc->dci_pdu[0],
				       dci_alloc->rnti,
				       dci_alloc->format,
690
				       &eNB->dlsch_SI,
691 692 693 694 695
				       fp,
				       eNB->pdsch_config_dedicated,
				       SI_RNTI,
				       0,
				       P_RNTI,
696 697
				       eNB->UE_stats[0].DL_pmi_single,
				       0);
698 699
    
    
700
    eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE;
701
    
702
    LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
703
	  eNB->dlsch_SI->nCCE[subframe]);
704 705 706 707
    
#if defined(SMBV) 
    
    // configure SI DCI
708 709
    if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
      LOG_D(PHY,"[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",frame,subframe,i);
710 711 712 713 714 715 716 717 718 719 720 721 722 723
      smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", dci_alloc, i);
    }
    
#endif
    
    
  } else if (dci_alloc->ra_flag == 1) {  // This is format 1A allocation for RA
    // configure dlsch parameters and CCE index
    LOG_D(PHY,"Generating dlsch params for RA_RNTI\n");    
    generate_eNB_dlsch_params_from_dci(frame,
				       subframe,
				       &dci_alloc->dci_pdu[0],
				       dci_alloc->rnti,
				       dci_alloc->format,
724
				       &eNB->dlsch_ra,
725 726 727 728 729
				       fp,
				       eNB->pdsch_config_dedicated,
				       SI_RNTI,
				       dci_alloc->rnti,
				       P_RNTI,
730 731
				       eNB->UE_stats[0].DL_pmi_single,
				       0);
732 733
    
    
734
    eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE;
735
    
736
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
737
	  eNB->dlsch_ra->nCCE[subframe]);
738 739 740
#if defined(SMBV) 
    
    // configure RA DCI
741 742
    if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
      LOG_D(PHY,"[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",frame,subframe,i);
743
      smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", dci_alloc, i);
Raymond Knopp's avatar
 
Raymond Knopp committed
744
    }
745 746 747 748 749 750 751 752 753 754
    
#endif
    
  }
  
  else if ((dci_alloc->format != format0)&&
	   (dci_alloc->format != format3)&&
	   (dci_alloc->format != format3A)&&
	   (dci_alloc->format != format4)){ // this is a normal DLSCH allocation
    
Raymond Knopp's avatar
 
Raymond Knopp committed
755

756 757 758 759
    
    if (UE_id>=0) {
#if defined(SMBV) 
      // Configure this user
760 761
      if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
	LOG_D(PHY,"[SMBV] Frame %3d, SF %d (SMBV SF %d) Configuring user %d with RNTI %"PRIu16" in TM%"PRIu8"\n",frame,subframe,(smbv_frame_cnt*10) + (subframe),UE_id+1,
762 763
              dci_alloc->rnti,eNB->transmission_mode[(uint8_t)UE_id]);
	smbv_configure_user(smbv_fname,UE_id+1,eNB->transmission_mode[(uint8_t)UE_id],dci_alloc->rnti);
Raymond Knopp's avatar
 
Raymond Knopp committed
764
      }
765 766
      
#endif
767

768 769 770 771 772 773
      LOG_D(PHY,"Generating dlsch params for RNTI %x\n",dci_alloc->rnti);      
      generate_eNB_dlsch_params_from_dci(frame,
					 subframe,
					 &dci_alloc->dci_pdu[0],
					 dci_alloc->rnti,
					 dci_alloc->format,
774
					 eNB->dlsch[(uint8_t)UE_id],
775 776 777 778 779
					 fp,
					 eNB->pdsch_config_dedicated,
					 SI_RNTI,
					 0,
					 P_RNTI,
780 781
					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single,
					 eNB->transmission_mode[(uint8_t)UE_id]<7?0:eNB->transmission_mode[(uint8_t)UE_id]);
782
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
783
	    eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
784 785
      
      
Cedric Roux's avatar
Cedric Roux committed
786 787
      T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
        T_INT(dci_alloc->rnti), T_INT(dci_alloc->format),
Cedric Roux's avatar
Cedric Roux committed
788
        T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid),
789 790
        T_INT(eNB->dlsch[(int)UE_id][0]->harq_processes[eNB->dlsch[(int)UE_id][0]->current_harq_pid]->mcs),
        T_INT(eNB->dlsch[(int)UE_id][0]->harq_processes[eNB->dlsch[(int)UE_id][0]->current_harq_pid]->TBS));
791

792
      eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
793
      
Cedric Roux's avatar
Cedric Roux committed
794
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
795
	    dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]);
796 797 798 799
      
#if defined(SMBV) 
      
      // configure UE-spec DCI
800 801
      if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
	LOG_D(PHY,"[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",frame,subframe,i);
802
	smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1,dci_alloc, i);
Raymond Knopp's avatar
 
Raymond Knopp committed
803
      }
804
      
805
#endif
806 807 808
      
      LOG_D(PHY,"[eNB %"PRIu8"][DCI][PDSCH %"PRIx16"] Frame %d subframe %d UE_id %"PRId8" Generated DCI format %d, aggregation %d\n",
	    eNB->Mod_id, dci_alloc->rnti,
809
	    frame, subframe,UE_id,
810 811
	    dci_alloc->format,
	    1<<dci_alloc->L);
Raymond Knopp's avatar
 
Raymond Knopp committed
812
    } else {
813
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n",
814
	    eNB->Mod_id,frame,dci_alloc->rnti);
815
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
816
  }
817 818
  
}
819

820
void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,const int UE_id) {
821

822
  int harq_pid;
823
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
824
  int frame = proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
825
  int subframe = proc->subframe_tx;
826

827
  LOG_D(PHY,
828 829 830
	"[eNB %"PRIu8"][PUSCH %"PRIu8"] Frame %d subframe %d UL Frame %"PRIu32", UL Subframe %"PRIu8", Generated ULSCH (format0) DCI (rnti %"PRIx16", dci %"PRIx8"), aggregation %d\n",
	eNB->Mod_id,
	subframe2harq_pid(fp,
831
			  pdcch_alloc2ul_frame(fp,frame,subframe),
832
			  pdcch_alloc2ul_subframe(fp,subframe)),
833
	frame,
834
	subframe,
835
	pdcch_alloc2ul_frame(fp,frame,subframe),
836 837 838 839 840
	pdcch_alloc2ul_subframe(fp,subframe),
	dci_alloc->rnti,
	dci_alloc->dci_pdu[0],
	1<<dci_alloc->L);
  
841
  generate_eNB_ulsch_params_from_dci(eNB,
842
				     proc,
843
				     &dci_alloc->dci_pdu[0],
844 845 846 847 848 849 850 851 852 853
				     dci_alloc->rnti,
				     format0,
				     UE_id,
				     SI_RNTI,
				     0,
				     P_RNTI,
				     CBA_RNTI,
				     0);  // do_srs
  
  LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d\n",
854
	eNB->Mod_id,frame,subframe,dci_alloc->rnti,
855 856 857 858 859
	dci_alloc->firstCCE);
  
#if defined(SMBV) 
  
  // configure UE-spec DCI for UL Grant
860 861
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
    LOG_D(PHY,"[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",frame,subframe,i);
862
    smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i);
Raymond Knopp's avatar
 
Raymond Knopp committed
863
  }
864 865 866 867 868 869
  
#endif
  
  
  // get the hard_pid for this subframe 
  harq_pid = subframe2harq_pid(fp,
870
			       pdcch_alloc2ul_frame(fp,frame,subframe),
871 872 873
			       pdcch_alloc2ul_subframe(fp,subframe));
  
  if (harq_pid==255) { // should not happen, log an error and exit, this is a fatal error
874
    LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,frame);
875 876 877 878
    mac_xface->macphy_exit("FATAL\n"); 
  }
  
  if ((dci_alloc->rnti  >= CBA_RNTI) && (dci_alloc->rnti < P_RNTI))
879
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1;
880
  else
881
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
882
  
Cedric Roux's avatar
Cedric Roux committed
883
  T(T_ENB_PHY_ULSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
Cedric Roux's avatar
Cedric Roux committed
884 885 886 887 888 889
    T_INT(dci_alloc->rnti), T_INT(harq_pid),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->mcs),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->round),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->first_rb),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->nb_rb),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->TBS));
890
}
891

892
void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols) {
893

894 895
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
896 897 898
  int harq_pid = dlsch->current_harq_pid;
  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
  int input_buffer_length = dlsch_harq->TBS/8;
899
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
900 901 902 903
  uint8_t *DLSCH_pdu=NULL;
  uint8_t DLSCH_pdu_tmp[768*8];
  uint8_t DLSCH_pdu_rar[256];
  int i;
904

905
  LOG_D(PHY,
Cedric Roux's avatar
Cedric Roux committed
906
	"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx64", rv %"PRIu8" (round %"PRIu8")\n",
907
	eNB->Mod_id, dlsch->rnti,harq_pid,
908
	frame, subframe, input_buffer_length,
909 910 911 912 913
	get_G(fp,
	      dlsch_harq->nb_rb,
	      dlsch_harq->rb_alloc,
	      get_Qm(dlsch_harq->mcs),
	      dlsch_harq->Nl,
914 915 916 917
	      num_pdcch_symbols,
	      frame,
	      subframe,
	      dlsch_harq->mimo_mode==TM7?7:0),
918 919 920 921 922
	dlsch_harq->nb_rb,
	dlsch_harq->mcs,
	pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	dlsch_harq->rvidx,
	dlsch_harq->round);
923

924
#if defined(MESSAGE_CHART_GENERATOR_PHY)
925 926 927 928 929 930 931 932 933 934 935
  MSC_LOG_TX_MESSAGE(
		     MSC_PHY_ENB,MSC_PHY_UE,
		     NULL,0,
		     "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
		     frame, subframe,
		     input_buffer_length,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
			   get_Qm(dlsch_harq->mcs),
			   dlsch_harq->Nl,
936 937 938 939
			   num_pdcch_symbols,
			   frame,
			   subframe,
			   dlsch_harq->mimo_mode==TM7?7:0),
940 941 942 943 944 945 946 947 948 949 950 951 952
		     dlsch_harq->nb_rb,
		     dlsch_harq->mcs,
		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
		     dlsch_harq->rvidx,
		     dlsch_harq->round);
#endif

  if (ue_stats) ue_stats->dlsch_sliding_cnt++;

  if (dlsch_harq->round == 0) {

    if (ue_stats)
      ue_stats->dlsch_trials[harq_pid][0]++;
953

954 955 956 957 958 959 960
    if (eNB->mac_enabled==1) {
      if (ra_flag == 0) {
	DLSCH_pdu = mac_xface->get_dlsch_sdu(eNB->Mod_id,
					     eNB->CC_id,
					     frame,
					     dlsch->rnti,
					     0);
Raymond Knopp's avatar
 
Raymond Knopp committed
961
      }
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
      else {
	int16_t crnti = mac_xface->fill_rar(eNB->Mod_id,
					    eNB->CC_id,
					    frame,
					    DLSCH_pdu_rar,
					    fp->N_RB_UL,
					    input_buffer_length);
	DLSCH_pdu = DLSCH_pdu_rar;

	int UE_id;

	if (crnti!=0) 
	  UE_id = add_ue(crnti,eNB);
	else 
	  UE_id = -1;
977
	    
978 979 980 981 982 983 984 985 986 987
	if (UE_id==-1) {
	  LOG_W(PHY,"[eNB] Max user count reached.\n");
	  mac_xface->cancel_ra_proc(eNB->Mod_id,
				    eNB->CC_id,
				    frame,
				    crnti);
	} else {
	  eNB->UE_stats[(uint32_t)UE_id].mode = RA_RESPONSE;
	  // Initialize indicator for first SR (to be cleared after ConnectionSetup is acknowledged)
	  eNB->first_sr[(uint32_t)UE_id] = 1;
988
	      
989 990 991 992 993
	  generate_eNB_ulsch_params_from_rar(DLSCH_pdu,
					     frame,
					     (subframe),
					     eNB->ulsch[(uint32_t)UE_id],
					     fp);
994
	      
995
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 1;
996
	      
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
	  get_Msg3_alloc(fp,
			 subframe,
			 frame,
			 &eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
			 &eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
	  LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n",
		frame,
		subframe,
		UE_id,
		eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
		eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
Cedric Roux's avatar
Cedric Roux committed
1008

1009 1010 1011 1012 1013 1014 1015 1016 1017
          /* TODO: get rid of this hack. The problem is that the eNodeB may
           * sometimes wrongly generate PHICH because somewhere 'phich_active' was
           * not reset to 0, due to an unidentified reason. When adding this
           * resetting here the problem seems to disappear completely.
           */
          LOG_D(PHY, "hack: set phich_active to 0 for UE %d fsf %d %d all HARQs\n", UE_id, frame, subframe);
          for (i = 0; i < 8; i++)
            eNB->ulsch[(uint32_t)UE_id]->harq_processes[i]->phich_active = 0;

1018 1019 1020
          mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, (uint16_t)crnti,
                                       eNB->ulsch[UE_id]->Msg3_frame, eNB->ulsch[UE_id]->Msg3_subframe);

Cedric Roux's avatar
Cedric Roux committed
1021 1022 1023
          T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
            T_INT(UE_id), T_INT((uint16_t)crnti), T_INT(1 /* 1 is for initial transmission*/),
            T_INT(eNB->ulsch[UE_id]->Msg3_frame), T_INT(eNB->ulsch[UE_id]->Msg3_subframe));
1024
	}
1025 1026 1027 1028 1029
	if (ue_stats) ue_stats->total_TBS_MAC += dlsch_harq->TBS;
      }
    }
    else {
      DLSCH_pdu = DLSCH_pdu_tmp;
1030
	  
1031 1032 1033
      for (i=0; i<input_buffer_length; i++)
	DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
    }
1034 1035
	
#if defined(SMBV) 
1036

1037 1038 1039 1040 1041
    // Configures the data source of allocation (allocation is configured by DCI)
    if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
      LOG_D(PHY,"[SMBV] Frame %3d, Configuring PDSCH payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt);
      //          smbv_configure_datalist_for_user(smbv_fname, find_ue(dlsch->rnti,eNB)+1, DLSCH_pdu, input_buffer_length);
    }
1042

1043
#endif
1044 1045 1046



1047 1048
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1049
    LOG_T(PHY,"eNB DLSCH SDU: \n");
1050

Cedric Roux's avatar
Cedric Roux committed
1051
    //eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE;
1052

1053 1054
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"/%u\n",eNB->Mod_id,eNB->proc[sched_subframe].frame_tx,subframe,
	  DCI_pdu->dci_alloc[i].rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe],DCI_pdu->dci_alloc[i].firstCCE);
1055

1056

1057 1058
    for (i=0; i<dlsch_harq->TBS>>3; i++)
      LOG_T(PHY,"%"PRIx8".",DLSCH_pdu[i]);
1059

1060
    LOG_T(PHY,"\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
1061
#endif
1062
#endif
1063 1064
  } else {
    ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++;
1065 1066
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1067
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
1068 1069
#endif
#endif
1070
  }
1071

1072
  if (eNB->abstraction_flag==0) {
1073

1074 1075 1076
    LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag);
    // 36-212
    start_meas(&eNB->dlsch_encoding_stats);
1077 1078 1079 1080 1081 1082 1083 1084
    eNB->te(eNB,
	    DLSCH_pdu,
	    num_pdcch_symbols,
	    dlsch,
	    frame,subframe,
	    &eNB->dlsch_rate_matching_stats,
	    &eNB->dlsch_turbo_encoding_stats,
	    &eNB->dlsch_interleaving_stats);
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
    stop_meas(&eNB->dlsch_encoding_stats);
    // 36-211
    start_meas(&eNB->dlsch_scrambling_stats);
    dlsch_scrambling(fp,
		     0,
		     dlsch,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
			   get_Qm(dlsch_harq->mcs),
			   dlsch_harq->Nl,
1096 1097 1098
			   num_pdcch_symbols,
			   frame,subframe,
			   0),
1099 1100 1101
		     0,
		     subframe<<1);
    stop_meas(&eNB->dlsch_scrambling_stats);
1102

1103 1104 1105
    start_meas(&eNB->dlsch_modulation_stats);


1106 1107
    dlsch_modulation(eNB,
		     eNB->common_vars.txdataF[0],
1108 1109 1110 1111 1112
		     AMP,
		     subframe,
		     num_pdcch_symbols,
		     dlsch,
		     dlsch1);
1113
	
1114 1115
    stop_meas(&eNB->dlsch_modulation_stats);
  }
1116 1117


1118
#ifdef PHY_ABSTRACTION
1119 1120 1121 1122 1123 1124 1125
  else {
    start_meas(&eNB->dlsch_encoding_stats);
    dlsch_encoding_emul(eNB,
			DLSCH_pdu,
			dlsch);
    stop_meas(&eNB->dlsch_encoding_stats);
  }
1126

Raymond Knopp's avatar
 
Raymond Knopp committed
1127
#endif
1128
  dlsch->active = 0;
1129
}
1130

1131
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
1132
			   eNB_rxtx_proc_t *proc,
1133
                           relaying_type_t r_type,
1134 1135
			   PHY_VARS_RN *rn,
			   int do_meas)
1136 1137
{
  UNUSED(rn);
1138 1139
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
1140
  //  uint16_t input_buffer_length;
1141
  uint32_t i,j,aa;
1142 1143 1144
  uint8_t harq_pid;
  DCI_PDU *DCI_pdu;
  DCI_PDU DCI_pdu_tmp;
1145
  int8_t UE_id=0;
1146 1147 1148
  uint8_t num_pdcch_symbols=0;
  uint8_t ul_subframe;
  uint32_t ul_frame;
1149
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1150
  DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL;
1151

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

1154 1155 1156
#if defined(SMBV) 
  // counts number of allocations in subframe
  // there is at least one allocation for PDCCH
1157
  uint8_t smbv_alloc_cnt = 1;Exiting eNB thread RXn_TXnp4
1158

1159
#endif
1160

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

1163
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
1164
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
1165

Cedric Roux's avatar
Cedric Roux committed
1166
  T(T_ENB_PHY_DL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
1167

1168 1169
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    // If we've dropped the UE, go back to PRACH mode for this UE
1170 1171 1172
    if ((frame==0)&&(subframe==0)) {
      if (eNB->UE_stats[i].crnti > 0) {
	LOG_I(PHY,"UE %d : rnti %x\n",i,eNB->UE_stats[i].crnti);
1173
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1174
    }
1175
    if (eNB->UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) {
1176
      LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n",
1177 1178
            eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->UE_stats[i].ulsch_consecutive_errors);
      eNB->UE_stats[i].ulsch_consecutive_errors=0;
1179 1180 1181
      mac_xface->UL_failure_indication(eNB->Mod_id,
				       eNB->CC_id,
				       frame,
1182
				       eNB->UE_stats[i].crnti,
1183 1184
				       subframe);
				       
Raymond Knopp's avatar
 
Raymond Knopp committed
1185
    }
1186
	
1187

Raymond Knopp's avatar
 
Raymond Knopp committed
1188
  }
1189 1190 1191


  // Get scheduling info for next subframe
1192
  // This is called only for the CC_id = 0 and triggers scheduling for all CC_id's
1193 1194
  if (eNB->mac_enabled==1) {
    if (eNB->CC_id == 0) {
1195
      mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,frame,subframe);//,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1196
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1197
  }
1198

1199
  // clear the transmit data array for the current subframe
1200
  if (eNB->abstraction_flag==0) {
1201
    for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {      
1202
      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
1203
             0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
Raymond Knopp's avatar
 
Raymond Knopp committed
1204
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1205
  }
1206

1207
  if (is_pmch_subframe(frame,subframe,fp)) {
1208
    pmch_procedures(eNB,proc,rn,r_type);
1209 1210 1211
  }
  else {
    // this is not a pmch subframe, so generate PSS/SSS/PBCH
1212
    common_signal_procedures(eNB,proc);
1213
  }
1214

1215
#if defined(SMBV) 
1216

Raymond Knopp's avatar
 
Raymond Knopp committed
1217
  // PBCH takes one allocation
1218
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
1219
    if (subframe==0)
Raymond Knopp's avatar
 
Raymond Knopp committed
1220 1221
      smbv_alloc_cnt++;
  }
1222

1223
#endif
1224

1225
  if (eNB->mac_enabled==1) {
1226 1227
    // Parse DCI received from MAC
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
1228 1229
    DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
				     eNB->CC_id,
1230
				     frame,
1231 1232 1233 1234
				     subframe);
  }
  else {
    DCI_pdu = &DCI_pdu_tmp;
1235
#ifdef EMOS_CHANNEL
1236
    fill_dci_emos(DCI_pdu,eNB);
1237
#else
1238
    fill_dci(DCI_pdu,eNB,proc);
1239 1240 1241 1242 1243 1244 1245 1246
    // clear previous allocation information for all UEs
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
      if (eNB->dlsch[i][0]){
        for (j=0; j<8; j++)
          eNB->dlsch[i][0]->harq_processes[j]->round = 0;
      }
    }

1247
#endif
1248
  }
1249

Raymond Knopp's avatar
 
Raymond Knopp committed
1250
  // clear existing ulsch dci allocations before applying info from MAC  (this is table
1251
  ul_subframe = pdcch_alloc2ul_subframe(fp,subframe);
1252
  ul_frame = pdcch_alloc2ul_frame(fp,frame,subframe);
1253

1254 1255 1256
  if ((subframe_select(fp,ul_subframe)==SF_UL) ||
      (fp->frame_type == FDD)) {
    harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
1257

1258
    // clear DCI allocation maps for new subframe
1259
    for (i=0; i<NUMBER_OF_UE_MAX; i++)
1260 1261 1262
      if (eNB->ulsch[i]) {
        eNB->ulsch[i]->harq_processes[harq_pid]->dci_alloc=0;
        eNB->ulsch[i]->harq_processes[harq_pid]->rar_alloc=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1263 1264
      }
  }
1265

Raymond Knopp's avatar
 
Raymond Knopp committed
1266
  // clear previous allocation information for all UEs
1267
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
1268 1269
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1270
  }
1271

1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
  /* save old HARQ information needed for PHICH generation */
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    if (eNB->ulsch[i]) {
      /* 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.
       */
      if ((subframe_select(fp,ul_subframe)==SF_UL) ||
          (fp->frame_type == FDD)) {
        harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
        eNB->ulsch[i]->harq_processes[harq_pid]->previous_first_rb =
            eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
        eNB->ulsch[i]->harq_processes[harq_pid]->previous_n_DMRS =
            eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS;
      }
    }
  }

1304

1305
  num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
Raymond Knopp's avatar
Raymond Knopp committed
1306
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
1307 1308
        DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);

1309
#if defined(SMBV) 
Raymond Knopp's avatar
 
Raymond Knopp committed
1310
  // Sets up PDCCH and DCI table
1311 1312
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) {
    LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",frame,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
1313
    dump_dci(fp,&DCI_pdu->dci_alloc[0]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1314 1315
    smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
  }
1316 1317
#endif

1318 1319
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);

1320
  // loop over all DCIs for this subframe to generate DLSCH allocations
1321 1322 1323 1324 1325
  for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
    LOG_D(PHY,"[eNB] Subframe %d: DCI %d/%d : rnti %x, CCEind %d\n",subframe,i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,DCI_pdu->dci_alloc[i].rnti,DCI_pdu->dci_alloc[i].firstCCE);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].rnti);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].format);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].firstCCE);
1326
    dci_alloc = &DCI_pdu->dci_alloc[i];
1327

1328 1329 1330 1331
    if ((dci_alloc->rnti<= P_RNTI) && 
	(dci_alloc->ra_flag!=1)) {
      if (eNB->mac_enabled==1)
	UE_id = find_ue((int16_t)dci_alloc->rnti,eNB);
1332 1333
      else
	UE_id = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1334
    }
1335 1336
    else UE_id=0;
    
1337
    generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
1338

Raymond Knopp's avatar
 
Raymond Knopp committed
1339
  }
1340

1341 1342
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

Raymond Knopp's avatar
 
Raymond Knopp committed
1343
  // Apply physicalConfigDedicated if needed
1344 1345 1346 1347
  // This is for UEs that have received this IE, which changes these DL and UL configuration, we apply after a delay for the eNodeB UL parameters
  phy_config_dedicated_eNB_step2(eNB);
  
  // Now loop again over the DCIs for UL configuration
1348
  for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
Cedric Roux's avatar
Cedric Roux committed
1349
    dci_alloc = &DCI_pdu->dci_alloc[i];
Raymond Knopp's avatar
 
Raymond Knopp committed
1350

1351 1352 1353
    if (dci_alloc->format == format0) {  // this is a ULSCH allocation
      if (eNB->mac_enabled==1)
	UE_id = find_ue((int16_t)dci_alloc->rnti,eNB);
1354 1355
      else
	UE_id = i;
1356
      
1357
      if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
1358
	LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
1359
	mac_xface->macphy_exit("FATAL\n"); 
1360
      }
1361
      generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1362
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1363
  }
1364

1365 1366


Lionel Gauthier's avatar
Lionel Gauthier committed
1367 1368


Raymond Knopp's avatar
 
Raymond Knopp committed
1369 1370
  // if we have DCI to generate do it now
  if ((DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci)>0) {
Lionel Gauthier's avatar
Lionel Gauthier committed
1371

1372 1373

  } else { // for emulation!!
1374 1375
    eNB->num_ue_spec_dci[(subframe)&1]=0;
    eNB->num_common_dci[(subframe)&1]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1376
  }
1377

1378
  if (eNB->abstraction_flag == 0) {
1379

1380
    if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) {
1381
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,frame, subframe,
1382
            DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
1383 1384
    }

1385 1386 1387 1388 1389 1390

    num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_ue_spec_dci,
                                         DCI_pdu->Num_common_dci,
                                         DCI_pdu->dci_alloc,
                                         0,
                                         AMP,
1391
                                         fp,
1392
                                         eNB->common_vars.txdataF[0],
1393
                                         subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1394

Raymond Knopp's avatar
 
Raymond Knopp committed
1395
  }
1396

1397
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
Raymond Knopp's avatar
 
Raymond Knopp committed
1398
  else {
1399
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
1400
    num_pdcch_symbols = generate_dci_top_emul(eNB,DCI_pdu->Num_ue_spec_dci,DCI_pdu->Num_common_dci,DCI_pdu->dci_alloc,subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1401
  }
1402

1403 1404
#endif

1405
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
1406

Raymond Knopp's avatar
 
Raymond Knopp committed
1407
  // Check for SI activity
1408

1409
  if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
1410

1411
    pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols);
1412

1413
#if defined(SMBV) 
1414

Raymond Knopp's avatar
 
Raymond Knopp committed
1415
    // Configures the data source of allocation (allocation is configured by DCI)
1416 1417
    if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
      LOG_D(PHY,"[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt);
Raymond Knopp's avatar
 
Raymond Knopp committed
1418 1419
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
    }
1420 1421

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1422
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1423

Raymond Knopp's avatar
 
Raymond Knopp committed
1424
  // Check for RA activity
1425
  if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
1426

1427
#if defined(SMBV) 
1428

1429
    // Configures the data source of allocation (allocation is configured by DCI)
1430 1431
    if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
      LOG_D(PHY,"[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt);
1432 1433 1434
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length);
    }
    
1435
#endif
1436 1437
    
    
1438
    LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA),Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n",
1439
	  eNB->Mod_id,
1440
	  frame, subframe,
1441 1442
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
1443
    
1444
    pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols);
1445 1446
    
    
1447
    eNB->dlsch_ra->active = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1448
  }
1449

Raymond Knopp's avatar
 
Raymond Knopp committed
1450
  // Now scan UE specific DLSCH
1451
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
1452 1453 1454 1455
    {
      if ((eNB->dlsch[(uint8_t)UE_id][0])&&
	  (eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&&
	  (eNB->dlsch[(uint8_t)UE_id][0]->active == 1)) {
1456

1457
	pdsch_procedures(eNB,proc,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols);
1458 1459


Raymond Knopp's avatar
 
Raymond Knopp committed
1460
      }
1461

1462 1463 1464
      else if ((eNB->dlsch[(uint8_t)UE_id][0])&&
	       (eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&&
	       (eNB->dlsch[(uint8_t)UE_id][0]->active == 0)) {
1465

1466 1467
	// clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
	eNB->dlsch[(uint8_t)UE_id][0]->subframe_tx[subframe]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1468
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1469
    }
1470

1471 1472


Raymond Knopp's avatar
 
Raymond Knopp committed
1473
  // if we have PHICH to generate
1474

1475
  if (is_phich_subframe(fp,subframe))
1476 1477 1478 1479
    {
      generate_phich_top(eNB,
			 proc,
			 AMP,
1480
			 0);
1481
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1482

1483 1484


1485
#ifdef EMOS
1486
  phy_procedures_emos_eNB_TX(subframe, eNB);
Raymond Knopp's avatar
 
Raymond Knopp committed
1487
#endif
1488

1489
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
1490
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
1491
  
1492 1493
}

1494
void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid)
1495
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1496
  // this prepares the demodulation of the first PUSCH of a new user, containing Msg3
1497 1498
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1499

Raymond Knopp's avatar
 
Raymond Knopp committed
1500
  LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
1501
        eNB->Mod_id,
1502
        frame,subframe,
1503 1504 1505 1506
        UE_id,eNB->ulsch[(uint32_t)UE_id]->Msg3_active,
        eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe,
        eNB->ulsch[(uint32_t)UE_id]->Msg3_frame);
  eNB->ulsch[(uint32_t)UE_id]->Msg3_flag = 0;
1507

1508 1509 1510
  if ((eNB->ulsch[(uint32_t)UE_id]->Msg3_active == 1) &&
      (eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe == subframe) &&
      (eNB->ulsch[(uint32_t)UE_id]->Msg3_frame == (uint32_t)frame))   {
1511

1512
    //    harq_pid = 0;
1513

1514 1515 1516
    eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 0;
    eNB->ulsch[(uint32_t)UE_id]->Msg3_flag = 1;
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag=1;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
1517
    LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
1518
          eNB->Mod_id,
1519
          frame,subframe,UE_id);
1520 1521 1522 1523 1524 1525 1526 1527 1528
  }
}


// This function retrieves the harq_pid of the corresponding DLSCH process
// and updates the error statistics of the DLSCH based on the received ACK
// info from UE along with the round index.  It also performs the fine-grain
// rate-adaptation based on the error statistics derived from the ACK/NAK process

1529
void process_HARQ_feedback(uint8_t UE_id,
1530
                           PHY_VARS_eNB *eNB,
1531
			   eNB_rxtx_proc_t *proc,
1532 1533 1534 1535 1536
                           uint8_t pusch_flag,
                           uint8_t *pucch_payload,
                           uint8_t pucch_sel,
                           uint8_t SR_payload)
{
1537

1538
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1539
  uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe;
1540 1541
  LTE_eNB_DLSCH_t *dlsch             =  eNB->dlsch[(uint32_t)UE_id][0];
  LTE_eNB_UE_stats *ue_stats         =  &eNB->UE_stats[(uint32_t)UE_id];
1542
  LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
1543
  uint8_t subframe_m4,M,m;
1544 1545
  int mp;
  int all_ACKed=1,nb_alloc=0,nb_ACK=0;
1546 1547
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1548
  int harq_pid = subframe2harq_pid( fp,frame,subframe);
1549

1550
  if (fp->frame_type == FDD) { //FDD
1551
    subframe_m4 = (subframe<4) ? subframe+6 : subframe-4;
1552

1553 1554
    dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
    M=1;
1555

1556
    if (pusch_flag == 1) {
1557
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1558
      if (dlsch->subframe_tx[subframe_m4]==1)
1559 1560
	LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUSCH for subframe %d\n",eNB->Mod_id,
	      frame,dlsch_ACK[0],subframe_m4);
1561 1562
    }
    else {
1563
      dlsch_ACK[0] = pucch_payload[0];
1564
      LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",eNB->Mod_id,
1565
	    frame,dlsch_ACK[0],subframe_m4);
kaltenbe's avatar
kaltenbe committed
1566
      /*
1567
	if (dlsch_ACK[0]==0)
1568
	AssertFatal(0,"Exiting on NAK on PUCCH\n");
kaltenbe's avatar
kaltenbe committed
1569
      */
1570
    }
1571

Lionel Gauthier's avatar
Lionel Gauthier committed
1572 1573 1574

#if defined(MESSAGE_CHART_GENERATOR_PHY)
    MSC_LOG_RX_MESSAGE(
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
		       MSC_PHY_ENB,MSC_PHY_UE,
		       NULL,0,
		       "%05u:%02u %s received %s  rnti %x harq id %u  tx SF %u",
		       frame,subframe,
		       (pusch_flag == 1)?"PUSCH":"PUCCH",
		       (dlsch_ACK[0])?"ACK":"NACK",
		       dlsch->rnti,
		       dl_harq_pid[0],
		       subframe_m4
		       );
Lionel Gauthier's avatar
Lionel Gauthier committed
1585
#endif
1586 1587
  } else { // TDD Handle M=1,2 cases only

1588
    M=ul_ACK_subframe2_M(fp,
1589 1590
                         subframe);

1591 1592 1593 1594 1595 1596 1597 1598
    // Now derive ACK information for TDD
    if (pusch_flag == 1) { // Do PUSCH ACK/NAK first
      // detect missing DAI
      //FK: this code is just a guess
      //RK: not exactly, yes if scheduled from PHICH (i.e. no DCI format 0)
      //    otherwise, it depends on how many of the PDSCH in the set are scheduled, we can leave it like this,
      //    but we have to adapt the code below.  For example, if only one out of 2 are scheduled, only 1 bit o_ACK is used

1599
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1600
      dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling)
1601
	?eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0]:eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[1];
1602
    }
1603

1604
    else {  // PUCCH ACK/NAK
1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639
      if ((SR_payload == 1)&&(pucch_sel!=2)) {  // decode Table 7.3 if multiplexing and SR=1
        nb_ACK = 0;

        if (M == 2) {
          if ((pucch_payload[0] == 1) && (pucch_payload[1] == 1)) // b[0],b[1]
            nb_ACK = 1;
          else if ((pucch_payload[0] == 1) && (pucch_payload[1] == 0))
            nb_ACK = 2;
        } else if (M == 3) {
          if ((pucch_payload[0] == 1) && (pucch_payload[1] == 1))
            nb_ACK = 1;
          else if ((pucch_payload[0] == 1) && (pucch_payload[1] == 0))
            nb_ACK = 2;
          else if ((pucch_payload[0] == 0) && (pucch_payload[1] == 1))
            nb_ACK = 3;
        }
      } else if (pucch_sel == 2) { // bundling or M=1
        dlsch_ACK[0] = pucch_payload[0];
        dlsch_ACK[1] = pucch_payload[0];
      } else { // multiplexing with no SR, this is table 10.1
        if (M==1)
          dlsch_ACK[0] = pucch_payload[0];
        else if (M==2) {
          if (((pucch_sel == 1) && (pucch_payload[0] == 1) && (pucch_payload[1] == 1)) ||
              ((pucch_sel == 0) && (pucch_payload[0] == 0) && (pucch_payload[1] == 1)))
            dlsch_ACK[0] = 1;
          else
            dlsch_ACK[0] = 0;

          if (((pucch_sel == 1) && (pucch_payload[0] == 1) && (pucch_payload[1] == 1)) ||
              ((pucch_sel == 1) && (pucch_payload[0] == 0) && (pucch_payload[1] == 0)))
            dlsch_ACK[1] = 1;
          else
            dlsch_ACK[1] = 0;
        }
1640
      }
1641
    }
1642 1643 1644 1645
  }

  // handle case where positive SR was transmitted with multiplexing
  if ((SR_payload == 1)&&(pucch_sel!=2)&&(pusch_flag == 0)) {
1646
    nb_alloc = 0;
1647 1648

    for (m=0; m<M; m++) {
1649
      dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1650 1651
						 subframe,
						 m);
1652 1653 1654

      if (dlsch->subframe_tx[dl_subframe]==1)
        nb_alloc++;
1655
    }
1656

1657 1658
    if (nb_alloc == nb_ACK)
      all_ACKed = 1;
1659
    else
1660
      all_ACKed = 0;
1661 1662 1663
  }


1664
  for (m=0,mp=-1; m<M; m++) {
1665

1666
    dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1667 1668
					       subframe,
					       m);
1669

1670 1671
    if (dlsch->subframe_tx[dl_subframe]==1) {
      if (pusch_flag == 1)
1672
        mp++;
1673
      else
1674
        mp = m;
1675

1676
      dl_harq_pid[m]     = dlsch->harq_ids[dl_subframe];
1677
      harq_pid_updated[UE_id][dl_harq_pid[m]] = 1;
1678

1679
      if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
1680 1681 1682 1683
        if ((SR_payload == 1)&&(all_ACKed == 1))
          dlsch_ACK[m] = 1;
        else
          dlsch_ACK[m] = 0;
1684
      }
1685

1686
      if (dl_harq_pid[m]<dlsch->Mdlharq) {
1687 1688
        dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
1689
        LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id,
1690 1691 1692 1693 1694 1695 1696 1697 1698
              dlsch->rnti,dl_harq_pid[m],dl_subframe,
              dlsch_harq_proc->status,dlsch_harq_proc->round,
              dlsch->harq_processes[dl_harq_pid[m]]->mcs,
              dlsch->harq_processes[dl_harq_pid[m]]->rvidx,
              dlsch->harq_processes[dl_harq_pid[m]]->TBS);

        if (dlsch_harq_proc->status==DISABLED)
          LOG_E(PHY,"dlsch_harq_proc is disabled? \n");

1699
#endif
1700 1701 1702 1703 1704 1705 1706 1707

        if ((dl_harq_pid[m]<dlsch->Mdlharq) &&
            (dlsch_harq_proc->status == ACTIVE)) {
          // dl_harq_pid of DLSCH is still active

          if ( dlsch_ACK[mp]==0) {
            // Received NAK
#ifdef DEBUG_PHY_PROC
1708
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] M = %d, m= %d, mp=%d NAK Received in round %d, requesting retransmission\n",eNB->Mod_id,
1709
                  dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
1710
#endif
1711

1712
            T(T_ENB_PHY_DLSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id), T_INT(dlsch->rnti),
1713
              T_INT(dl_harq_pid[m]));
1714

1715 1716 1717 1718 1719 1720 1721 1722 1723
            if (dlsch_harq_proc->round == 0)
              ue_stats->dlsch_NAK_round0++;

            ue_stats->dlsch_NAK[dl_harq_pid[m]][dlsch_harq_proc->round]++;


            // then Increment DLSCH round index
            dlsch_harq_proc->round++;

1724

1725
            if (dlsch_harq_proc->round == dlsch->Mlimit) {
1726 1727
              // This was the last round for DLSCH so reset round and increment l2_error counter
#ifdef DEBUG_PHY_PROC
1728
              LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",eNB->Mod_id,
1729
                    dlsch->rnti,dl_harq_pid[m]);
1730
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1731
#if defined(MESSAGE_CHART_GENERATOR_PHY)
1732
              MSC_LOG_EVENT(MSC_PHY_ENB, "0 HARQ DLSCH Failed RNTI %"PRIx16" round %u",
1733 1734
                            dlsch->rnti,
                            dlsch_harq_proc->round);
Lionel Gauthier's avatar
Lionel Gauthier committed
1735
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1736

1737 1738 1739 1740 1741 1742 1743
              dlsch_harq_proc->round = 0;
              ue_stats->dlsch_l2_errors[dl_harq_pid[m]]++;
              dlsch_harq_proc->status = SCH_IDLE;
              dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq;
            }
          } else {
#ifdef DEBUG_PHY_PROC
1744
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
1745
                  dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
1746
#endif
1747

1748
            T(T_ENB_PHY_DLSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id), T_INT(dlsch->rnti),
1749
              T_INT(dl_harq_pid[m]));
1750

1751 1752 1753 1754 1755 1756 1757 1758
            ue_stats->dlsch_ACK[dl_harq_pid[m]][dlsch_harq_proc->round]++;

            // Received ACK so set round to 0 and set dlsch_harq_pid IDLE
            dlsch_harq_proc->round  = 0;
            dlsch_harq_proc->status = SCH_IDLE;
            dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq;

            ue_stats->total_TBS = ue_stats->total_TBS +
1759
	      eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1760 1761
            /*
              ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
1762
              eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1763 1764
            */
          }
1765
	 
1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776
          // Do fine-grain rate-adaptation for DLSCH
          if (ue_stats->dlsch_NAK_round0 > dlsch->error_threshold) {
            if (ue_stats->dlsch_mcs_offset == 1)
              ue_stats->dlsch_mcs_offset=0;
            else
              ue_stats->dlsch_mcs_offset=-1;
          }

#ifdef DEBUG_PHY_PROC
          LOG_D(PHY,"[process_HARQ_feedback] Frame %d Setting round to %d for pid %d (subframe %d)\n",frame,
                dlsch_harq_proc->round,dl_harq_pid[m],subframe);
1777
#endif
1778
	  harq_pid_round[UE_id][dl_harq_pid[m]] = dlsch_harq_proc->round;
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797
          // Clear NAK stats and adjust mcs offset
          // after measurement window timer expires
          if (ue_stats->dlsch_sliding_cnt == dlsch->ra_window_size) {
            if ((ue_stats->dlsch_mcs_offset == 0) && (ue_stats->dlsch_NAK_round0 < 2))
              ue_stats->dlsch_mcs_offset = 1;

            if ((ue_stats->dlsch_mcs_offset == 1) && (ue_stats->dlsch_NAK_round0 > 2))
              ue_stats->dlsch_mcs_offset = 0;

            if ((ue_stats->dlsch_mcs_offset == 0) && (ue_stats->dlsch_NAK_round0 > 2))
              ue_stats->dlsch_mcs_offset = -1;

            if ((ue_stats->dlsch_mcs_offset == -1) && (ue_stats->dlsch_NAK_round0 < 2))
              ue_stats->dlsch_mcs_offset = 0;

            ue_stats->dlsch_NAK_round0 = 0;
            ue_stats->dlsch_sliding_cnt = 0;
          }
        }
1798
      }
1799
    }
1800 1801 1802
  }
}

1803
void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
1804
		      eNB_rxtx_proc_t *proc,
1805 1806 1807 1808 1809 1810
                      uint8_t UE_id,
                      int16_t *n1_pucch0,
                      int16_t *n1_pucch1,
                      int16_t *n1_pucch2,
                      int16_t *n1_pucch3)
{
1811

1812
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
1813
  uint8_t nCCE0,nCCE1;
1814
  int sf;
1815 1816
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1817 1818

  if (frame_parms->frame_type == FDD ) {
1819
    sf = (subframe<4) ? (subframe+6) : (subframe-4);
1820

1821 1822
    if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[sf]>0) {
      *n1_pucch0 = frame_parms->pucch_config_common.n1PUCCH_AN + eNB->dlsch[(uint32_t)UE_id][0]->nCCE[sf];
1823
      *n1_pucch1 = -1;
1824
    } else {
1825 1826 1827
      *n1_pucch0 = -1;
      *n1_pucch1 = -1;
    }
1828
  } else {
1829

1830 1831 1832
    switch (frame_parms->tdd_config) {
    case 1:  // DL:S:UL:UL:DL:DL:S:UL:UL:DL
      if (subframe == 2) {  // ACK subframes 5 and 6
1833
        /*  if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
1834 1835 1836 1837 1838
	    nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
	    *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
	    }
	    else
	    *n1_pucch1 = -1;*/
1839

1840 1841
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1842 1843 1844 1845 1846 1847 1848
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;

        *n1_pucch1 = -1;
      } else if (subframe == 3) { // ACK subframe 9

1849 1850
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1851 1852 1853 1854 1855 1856 1857 1858 1859
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;

        *n1_pucch1 = -1;

      } else if (subframe == 7) { // ACK subframes 0 and 1
        //harq_ack[0].nCCE;
        //harq_ack[1].nCCE;
1860 1861
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1862 1863 1864 1865 1866 1867 1868
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;

        *n1_pucch1 = -1;
      } else if (subframe == 8) { // ACK subframes 4
        //harq_ack[4].nCCE;
1869 1870
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4];
1871 1872 1873 1874 1875 1876 1877
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;

        *n1_pucch1 = -1;
      } else {
        LOG_D(PHY,"[eNB %d] frame %d: phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n",
1878
              eNB->Mod_id,
1879 1880 1881
              frame,
              subframe,frame_parms->tdd_config);
        return;
1882
      }
1883

1884
      break;
1885

1886 1887
    case 3:  // DL:S:UL:UL:UL:DL:DL:DL:DL:DL
      if (subframe == 2) {  // ACK subframes 5,6 and 1 (S in frame-2), forget about n-11 for the moment (S-subframe)
1888 1889
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
1890 1891 1892 1893
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1894 1895
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1896 1897 1898 1899 1900
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;
      } else if (subframe == 3) { // ACK subframes 7 and 8
        LOG_D(PHY,"get_n1_pucch_eNB : subframe 3, subframe_tx[7] %d, subframe_tx[8] %d\n",
1901
              eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7],eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]);
1902

1903 1904
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[8];
1905 1906 1907 1908 1909
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
          LOG_D(PHY,"nCCE1 %d, n1_pucch1 %d\n",nCCE1,*n1_pucch1);
        } else
          *n1_pucch1 = -1;

1910 1911
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7];
1912 1913 1914 1915 1916
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
          LOG_D(PHY,"nCCE0 %d, n1_pucch0 %d\n",nCCE0,*n1_pucch0);
        } else
          *n1_pucch0 = -1;
      } else if (subframe == 4) { // ACK subframes 9 and 0
1917 1918
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1919 1920 1921 1922
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1923 1924
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1925 1926 1927 1928 1929
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;
      } else {
        LOG_D(PHY,"[eNB %d] Frame %d: phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n",
1930
              eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
1931
        return;
1932
      }
1933

1934
      break;
1935 1936
    }  // switch tdd_config

1937 1938 1939
    // Don't handle the case M>2
    *n1_pucch2 = -1;
    *n1_pucch3 = -1;
1940 1941 1942
  }
}

1943
void prach_procedures(PHY_VARS_eNB *eNB) {
1944

1945
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1946 1947 1948 1949
  uint16_t preamble_energy_list[64],preamble_delay_list[64];
  uint16_t preamble_max,preamble_energy_max;
  uint16_t i;
  int8_t UE_id;
1950 1951
  int subframe = eNB->proc.subframe_prach;
  int frame = eNB->proc.frame_prach;
1952
  uint8_t CC_id = eNB->CC_id;
1953

1954
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
1955 1956
  memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
  memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
1957

1958
  if (eNB->abstraction_flag == 0) {
1959
    LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id, 
1960
          frame,subframe,dB_fixed(signal_energy(&eNB->common_vars.rxdata[0][0][subframe*fp->samples_per_tti],512)) - eNB->rx_total_gain_dB);
1961

1962

1963
    rx_prach(eNB,
1964 1965 1966 1967 1968 1969 1970
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
  } else {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {

1971
      LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
1972
            UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
1973
            PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
1974
            fp->prach_config_common.rootSequenceIndex,
1975 1976
            PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex);

Raymond Knopp's avatar
 
Raymond Knopp committed
1977
      if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) &&
1978
          (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex ==
1979
           fp->prach_config_common.rootSequenceIndex) ) {
1980 1981 1982
        preamble_energy_list[PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex] = 800;
        preamble_delay_list[PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex] = 5;

1983
      }
1984
    }
1985
  }
1986

1987 1988 1989
  preamble_energy_max = preamble_energy_list[0];
  preamble_max = 0;

1990
  for (i=1; i<64; i++) {
1991 1992 1993 1994
    if (preamble_energy_max < preamble_energy_list[i]) {
      preamble_energy_max = preamble_energy_list[i];
      preamble_max = i;
    }
1995 1996 1997
  }

#ifdef DEBUG_PHY_PROC
1998
  LOG_D(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
1999 2000 2001
        preamble_max,
        preamble_energy_list[preamble_max],
        preamble_delay_list[preamble_max]);
2002 2003
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
2004
  if (preamble_energy_list[preamble_max] > 580) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2005

2006
    UE_id = find_next_ue_index(eNB);
2007
 
2008
    if (UE_id>=0) {
2009
      eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
2010

2011
      eNB->UE_stats[(uint32_t)UE_id].sector = 0;
2012
      LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n",
2013 2014
            eNB->Mod_id,
            eNB->CC_id,
2015 2016
            frame,
            subframe,
2017
	    UE_id,
2018 2019 2020 2021
            preamble_max,
            preamble_energy_max/10,
            preamble_energy_max%10,
            preamble_delay_list[preamble_max]);
2022

Cedric Roux's avatar
Cedric Roux committed
2023 2024 2025
      T(T_ENB_PHY_INITIATE_RA_PROCEDURE, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
        T_INT(preamble_max), T_INT(preamble_energy_max), T_INT(preamble_delay_list[preamble_max]));

2026
      if (eNB->mac_enabled==1) {
2027 2028
        uint8_t update_TA  = 4;
	uint8_t update_TA2 = 1;
2029
        switch (fp->N_RB_DL) {
2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041
        case 6:
          update_TA = 16;
          break;

        case 25:
          update_TA = 4;
          break;

        case 50:
          update_TA = 2;
          break;

2042 2043 2044
	case 75:
	  update_TA  = 3;
	  update_TA2 = 2;
2045
        case 100:
2046
          update_TA  = 1;
2047 2048 2049
          break;
        }

2050 2051 2052 2053
	mac_xface->initiate_ra_proc(eNB->Mod_id,
				    eNB->CC_id,
				    frame,
				    preamble_max,
2054
				    preamble_delay_list[preamble_max]*update_TA/update_TA2,
2055
				    0,subframe,0);
2056 2057
      }      

2058
    } else {
2059
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many");
2060
      LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
2061
            eNB->Mod_id,frame, subframe);
2062
    }
2063
  }
2064
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
2065 2066
}

Cedric Roux's avatar
Cedric Roux committed
2067 2068
void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid)
{
2069
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2070
  uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0};
Cedric Roux's avatar
Cedric Roux committed
2071
  int16_t n1_pucch0 = -1, n1_pucch1 = -1, n1_pucch2 = -1, n1_pucch3 = -1;
2072 2073
  uint8_t do_SR = 0;
  uint8_t pucch_sel = 0;
2074
  int32_t metric0=0,metric1=0,metric0_SR=0;
2075 2076
  ANFBmode_t bundling_flag;
  PUCCH_FMT_t format;
2077 2078
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2079

2080 2081
  if ((eNB->dlsch[UE_id][0]) &&
      (eNB->dlsch[UE_id][0]->rnti>0) &&
Cedric Roux's avatar
Cedric Roux committed
2082
      (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) {
2083

2084
    // check SR availability
2085 2086
    do_SR = is_SR_subframe(eNB,proc,UE_id);
    //      do_SR = 0;
Cedric Roux's avatar
Cedric Roux committed
2087

2088 2089
    // Now ACK/NAK
    // First check subframe_tx flag for earlier subframes
2090

2091
    get_n1_pucch_eNB(eNB,
Cedric Roux's avatar
Cedric Roux committed
2092 2093 2094 2095 2096 2097 2098
                     proc,
                     UE_id,
                     &n1_pucch0,
                     &n1_pucch1,
                     &n1_pucch2,
                     &n1_pucch3);

2099
    LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d, subframe %d Checking for PUCCH (%d,%d,%d,%d) SR %d\n",
Cedric Roux's avatar
Cedric Roux committed
2100 2101 2102 2103
          eNB->Mod_id,eNB->dlsch[UE_id][0]->rnti,
          frame,subframe,
          n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR);

2104 2105 2106
    if ((n1_pucch0==-1) && (n1_pucch1==-1) && (do_SR==0)) {  // no TX PDSCH that have to be checked and no SR for this UE_id
    } else {
      // otherwise we have some PUCCH detection to do
Cedric Roux's avatar
Cedric Roux committed
2107

2108 2109 2110
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
Cedric Roux's avatar
Cedric Roux committed
2111 2112
        eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
        break;
2113
      case 15:
Cedric Roux's avatar
Cedric Roux committed
2114 2115
        eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
        break;
2116
      case 25:
Cedric Roux's avatar
Cedric Roux committed
2117 2118
        eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
        break;
2119
      case 50:
Cedric Roux's avatar
Cedric Roux committed
2120 2121 2122
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
        break;
2123
      case 75:
Cedric Roux's avatar
Cedric Roux committed
2124 2125 2126
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
        break;
2127
      case 100:
Cedric Roux's avatar
Cedric Roux committed
2128 2129 2130
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
        break;
2131
      default:
Cedric Roux's avatar
Cedric Roux committed
2132 2133
        LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
        break;
2134
      }
2135

2136
      if (do_SR == 1) {
Cedric Roux's avatar
Cedric Roux committed
2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158
        eNB->UE_stats[UE_id].sr_total++;


        if (eNB->abstraction_flag == 0) {
          metric0_SR = rx_pucch(eNB,
                                pucch_format1,
                                UE_id,
                                eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
                                0, // n2_pucch
                                0, // shortened format, should be use_srs flag, later
                                &SR_payload,
                                frame,
                                subframe,
                                PUCCH1_THRES);
          LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (SR n1pucch is %d)\n",
                eNB->Mod_id,
                eNB->ulsch[UE_id]->rnti,
                frame,
                subframe,
                SR_payload,
                eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex);
        }
2159
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
        else {
          metric0_SR = rx_pucch_emul(eNB,
                                     proc,
                                     UE_id,
                                     pucch_format1,
                                     0,
                                     &SR_payload);
          LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",eNB->Mod_id,
                eNB->ulsch[UE_id]->rnti,frame,subframe,SR_payload,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex);
        }
2170
#endif
2171
      }// do_SR==1
Cedric Roux's avatar
Cedric Roux committed
2172

2173
      if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR
Cedric Roux's avatar
Cedric Roux committed
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191
      } else if (fp->frame_type==FDD) { // FDD
        // if SR was detected, use the n1_pucch from SR, else use n1_pucch0
        //          n1_pucch0 = (SR_payload==1) ? eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex:n1_pucch0;

        LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload);

        if (eNB->abstraction_flag == 0) {
          metric0 = rx_pucch(eNB,
                             pucch_format1a,
                             UE_id,
                             (uint16_t)n1_pucch0,
                             0, //n2_pucch
                             0, // shortened format
                             pucch_payload0,
                             frame,
                             subframe,
                             PUCCH1a_THRES);
        }
2192
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2193 2194 2195 2196 2197 2198 2199 2200
        else {
          metric0 = rx_pucch_emul(eNB,
                                  proc,
                                  UE_id,
                                  pucch_format1a,
                                  0,
                                  pucch_payload0);
        }
2201
#endif
Cedric Roux's avatar
Cedric Roux committed
2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233

        /* cancel SR detection if reception on n1_pucch0 is better than on SR PUCCH resource index */
        if (do_SR && metric0 > metric0_SR) SR_payload = 0;

        if (do_SR && metric0 <= metric0_SR) {
          /* when transmitting ACK/NACK on SR PUCCH resource index, SR payload is always 1 */
          SR_payload = 1;

          if (eNB->abstraction_flag == 0) {
            metric0=rx_pucch(eNB,
                             pucch_format1a,
                             UE_id,
                             eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
                             0, //n2_pucch
                             0, // shortened format
                             pucch_payload0,
                             frame,
                             subframe,
                             PUCCH1a_THRES);
          }
#ifdef PHY_ABSTRACTION
          else {
            metric0 = rx_pucch_emul(eNB,
                                    proc,
                                    UE_id,
                                    pucch_format1a,
                                    0,
                                    pucch_payload0);
          }
#endif
        }

2234
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2235 2236 2237 2238 2239
        LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
            eNB->Mod_id,
            eNB->dlsch[UE_id][0]->rnti,
            frame,subframe,
            pucch_payload0[0],metric0);
2240
#endif
2241

Cedric Roux's avatar
Cedric Roux committed
2242 2243 2244 2245 2246 2247 2248
        process_HARQ_feedback(UE_id,eNB,proc,
                            0,// pusch_flag
                            pucch_payload0,
                            2,
                            SR_payload);
      } // FDD
      else {  //TDD
2249

Cedric Roux's avatar
Cedric Roux committed
2250
        bundling_flag = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode;
2251

Cedric Roux's avatar
Cedric Roux committed
2252
        // fix later for 2 TB case and format1b
Raymond Knopp's avatar
Raymond Knopp committed
2253

Cedric Roux's avatar
Cedric Roux committed
2254 2255 2256 2257 2258 2259 2260
        if ((fp->frame_type==FDD) ||
          (bundling_flag==bundling)    ||
          ((fp->frame_type==TDD)&&(fp->tdd_config==1)&&((subframe!=2)||(subframe!=7)))) {
          format = pucch_format1a;
        } else {
          format = pucch_format1b;
        }
2261

Cedric Roux's avatar
Cedric Roux committed
2262 2263
        // if SR was detected, use the n1_pucch from SR
        if (SR_payload==1) {
2264
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2265 2266 2267 2268
          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);
2269
#endif
2270

Cedric Roux's avatar
Cedric Roux committed
2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282
          if (eNB->abstraction_flag == 0)
            metric0 = rx_pucch(eNB,
                               format,
                               UE_id,
                               eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
                               0, //n2_pucch
                               0, // shortened format
                               pucch_payload0,
                               frame,
                               subframe,
                               PUCCH1a_THRES);
          else {
2283
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2284 2285 2286 2287 2288
            metric0 = rx_pucch_emul(eNB,proc,
                                    UE_id,
                                    format,
                                    0,
                                    pucch_payload0);
2289
#endif
Cedric Roux's avatar
Cedric Roux committed
2290 2291
          }
        } else { //using n1_pucch0/n1_pucch1 resources
2292
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2293 2294 2295 2296
          LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",eNB->Mod_id,
                eNB->dlsch[UE_id][0]->rnti,
                frame,subframe,
                n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
2297
#endif
Cedric Roux's avatar
Cedric Roux committed
2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314
          metric0=0;
          metric1=0;

          // Check n1_pucch0 metric
          if (n1_pucch0 != -1) {
            if (eNB->abstraction_flag == 0)
              metric0 = rx_pucch(eNB,
                                 format,
                                 UE_id,
                                 (uint16_t)n1_pucch0,
                                 0, // n2_pucch
                                 0, // shortened format
                                 pucch_payload0,
                                 frame,
                                 subframe,
                                 PUCCH1a_THRES);
            else {
2315
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2316 2317 2318 2319 2320 2321
              metric0 = rx_pucch_emul(eNB,
                                      proc,
                                      UE_id,
                                      format,
                                      0,
                                      pucch_payload0);
2322
#endif
Cedric Roux's avatar
Cedric Roux committed
2323 2324
            }
          }
2325

Cedric Roux's avatar
Cedric Roux committed
2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339
          // Check n1_pucch1 metric
          if (n1_pucch1 != -1) {
            if (eNB->abstraction_flag == 0)
              metric1 = rx_pucch(eNB,
                                 format,
                                 UE_id,
                                 (uint16_t)n1_pucch1,
                                 0, //n2_pucch
                                 0, // shortened format
                                 pucch_payload1,
                                 frame,
                                 subframe,
                                 PUCCH1a_THRES);
            else {
2340
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2341 2342 2343 2344 2345 2346
              metric1 = rx_pucch_emul(eNB,
                                      proc,
                                      UE_id,
                                      format,
                                      1,
                                      pucch_payload1);
2347
#endif
Cedric Roux's avatar
Cedric Roux committed
2348 2349 2350
            }
          }
        }
2351

Cedric Roux's avatar
Cedric Roux committed
2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367
        if (SR_payload == 1) {
          pucch_payload = pucch_payload0;

          if (bundling_flag == bundling)
            pucch_sel = 2;
        } else if (bundling_flag == multiplexing) { // multiplexing + no SR
          pucch_payload = (metric1>metric0) ? pucch_payload1 : pucch_payload0;
          pucch_sel     = (metric1>metric0) ? 1 : 0;
        } else { // bundling + no SR
          if (n1_pucch1 != -1)
            pucch_payload = pucch_payload1;
          else if (n1_pucch0 != -1)
            pucch_payload = pucch_payload0;

          pucch_sel = 2;  // indicate that this is a bundled ACK/NAK
        }
2368

2369
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2370 2371 2372 2373
        LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, sel %d, (%d,%d)\n",eNB->Mod_id,
              eNB->dlsch[UE_id][0]->rnti,
              frame,subframe,
              metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]);
2374
#endif
Cedric Roux's avatar
Cedric Roux committed
2375 2376 2377 2378 2379 2380
        process_HARQ_feedback(UE_id,eNB,proc,
                              0,// pusch_flag
                              pucch_payload,
                              pucch_sel,
                              SR_payload);
      } // TDD
2381
    }
Cedric Roux's avatar
Cedric Roux committed
2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404

    if (SR_payload == 1) {
      LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id,
            eNB->ulsch[UE_id]->rnti,frame,subframe);
      eNB->UE_stats[UE_id].sr_received++;

      if (eNB->first_sr[UE_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
        eNB->first_sr[UE_id] = 0;
        eNB->dlsch[UE_id][0]->harq_processes[0]->round=0;
        eNB->dlsch[UE_id][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[UE_id]->rnti,frame,subframe);
      }

      if (eNB->mac_enabled==1) {
        mac_xface->SR_indication(eNB->Mod_id,
                                 eNB->CC_id,
                                 frame,
                                 eNB->dlsch[UE_id][0]->rnti,subframe);
      }
    }
  }
2405
}
2406

2407

2408
void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
2409

2410 2411
  uint8_t access_mode;
  int num_active_cba_groups;
2412 2413
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2414 2415
  uint16_t rnti=0;
  int ret=0;
2416
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2417

2418 2419
  if (eNB->ulsch[UE_id]==NULL) return;

2420
  num_active_cba_groups = eNB->ulsch[UE_id]->num_active_cba_groups;
2421 2422
 
  if ((num_active_cba_groups > 0) &&
2423 2424
      (eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups]>0) &&
      (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag==1)) {
2425 2426 2427 2428
    rnti=0;
    
#ifdef DEBUG_PHY_PROC
    LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Checking PUSCH/ULSCH CBA Reception for UE %d with cba rnti %x mode %s\n",
2429
	  eNB->Mod_id,harq_pid,
2430
	  frame,subframe,
2431
	  UE_id, (uint16_t)eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->UE_stats[UE_id].mode]);
2432
#endif
2433
    
2434
    if (eNB->abstraction_flag==0) {
2435
      rx_ulsch(eNB,proc,
2436
	       eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2437
	       UE_id,
2438
	       eNB->ulsch,
2439 2440 2441 2442 2443
	       0);
    }
    
#ifdef PHY_ABSTRACTION
    else {
2444
      rx_ulsch_emul(eNB,proc,
2445
		    eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2446
		    UE_id);
2447 2448
    }
    
2449
#endif
2450
    
2451
    if (eNB->abstraction_flag == 0) {
2452
      ret = ulsch_decoding(eNB,proc,
2453 2454
			   UE_id,
			   0, // control_only_flag
2455 2456
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->V_UL_DAI,
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2457 2458 2459 2460
    }
    
#ifdef PHY_ABSTRACTION
    else {
2461
      ret = ulsch_decoding_emul(eNB,
2462
				proc,
2463 2464 2465 2466 2467 2468
				UE_id,
				&rnti);
    }
    
#endif
    
2469
    if (eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2470
#ifdef DEBUG_PHY_PROC
2471
      
2472
      print_CQI(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o,eNB->ulsch[UE_id]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
2473 2474
#endif
      access_mode = UNKNOWN_ACCESS;
2475 2476 2477
      extract_CQI(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o,
		  eNB->ulsch[UE_id]->harq_processes[harq_pid]->uci_format,
		  &eNB->UE_stats[UE_id],
2478
		  fp->N_RB_DL,
2479
		  &rnti, &access_mode);
2480
      eNB->UE_stats[UE_id].rank = eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_RI[0];
2481 2482
    }
    
2483 2484
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0;
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE;
2485
      
2486 2487 2488 2489
    if ((num_active_cba_groups > 0) &&
	(UE_id + num_active_cba_groups < NUMBER_OF_UE_MAX) &&
	(eNB->ulsch[UE_id+num_active_cba_groups]->cba_rnti[UE_id%num_active_cba_groups] > 0 ) &&
	(eNB->ulsch[UE_id+num_active_cba_groups]->num_active_cba_groups> 0)) {
2490
#ifdef DEBUG_PHY_PROC
2491 2492 2493
      LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d resetting the subframe_scheduling_flag for Ue %d cba groups %d members\n",
	    eNB->Mod_id,harq_pid,frame,subframe,UE_id,harq_pid,
	    UE_id+num_active_cba_groups, UE_id%eNB->ulsch[UE_id]->num_active_cba_groups);
2494
#endif
2495 2496 2497 2498
      eNB->ulsch[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=1;
      eNB->ulsch[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->status= CBA_ACTIVE;
      eNB->ulsch[UE_id+num_active_cba_groups]->harq_processes[harq_pid]->TBS=eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS;
    }
2499

2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
    if (ret == (1+MAX_TURBO_ITERATIONS)) {
      eNB->UE_stats[UE_id].ulsch_round_errors[harq_pid][eNB->ulsch[UE_id]->harq_processes[harq_pid]->round]++;
      eNB->ulsch[UE_id]->harq_processes[harq_pid]->phich_active = 1;
      eNB->ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK = 0;
      eNB->ulsch[UE_id]->harq_processes[harq_pid]->round++;
    } // ulsch in error
    else {
      LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
	    eNB->Mod_id,harq_pid,
	    frame,subframe);

      eNB->ulsch[UE_id]->harq_processes[harq_pid]->phich_active = 1;
      eNB->ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK = 1;
      eNB->ulsch[UE_id]->harq_processes[harq_pid]->round = 0;
      eNB->UE_stats[UE_id].ulsch_consecutive_errors = 0;
2515 2516
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534
      LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",
	    frame,subframe,
	    harq_pid,eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3);

      for (j=0; j<eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; j++)
	LOG_T(PHY,"%x.",eNB->ulsch[UE_id]->harq_processes[harq_pid]->b[j]);

      LOG_T(PHY,"\n");
#endif
#endif

      if (access_mode > UNKNOWN_ACCESS) {
	LOG_D(PHY,"[eNB %d] Frame %d, Subframe %d : received ULSCH SDU from CBA transmission, UE (%d,%x), CBA (group %d, rnti %x)\n",
	      eNB->Mod_id, frame,subframe,
	      UE_id, eNB->ulsch[UE_id]->rnti,
	      UE_id % eNB->ulsch[UE_id]->num_active_cba_groups, eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups]);

	// detect if there is a CBA collision
2535 2536
	if ((eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) && 
	    (eNB->mac_enabled==1)) {
2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564
	  mac_xface->rx_sdu(eNB->Mod_id,
			    eNB->CC_id,
			    frame,subframe,
			    eNB->ulsch[UE_id]->rnti,
			    eNB->ulsch[UE_id]->harq_processes[harq_pid]->b,
			    eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3,
			    harq_pid,
			    NULL);

	  eNB->cba_last_reception[UE_id%num_active_cba_groups]+=1;//(subframe);
	} else {
	  if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 1 )
	    LOG_N(PHY,"[eNB%d] Frame %d subframe %d : first CBA collision detected \n ",
		  eNB->Mod_id,frame,subframe);

	  LOG_N(PHY,"[eNB%d] Frame %d subframe %d : CBA collision set SR for UE %d in group %d \n ",
		eNB->Mod_id,frame,subframe,
		eNB->cba_last_reception[UE_id%num_active_cba_groups],UE_id%num_active_cba_groups );

	  eNB->cba_last_reception[UE_id%num_active_cba_groups]+=1;

	  mac_xface->SR_indication(eNB->Mod_id,
				   eNB->CC_id,
				   frame,
				   eNB->dlsch[UE_id][0]->rnti,subframe);
	}
      } // UNKNOWN_ACCESS
    } // ULSCH CBA not in error
2565
  }
2566

2567
}
2568

2569 2570 2571 2572
typedef struct {
  PHY_VARS_eNB *eNB;
  int slot;
} fep_task;
2573

2574
void fep0(PHY_VARS_eNB *eNB,int slot) {
2575

2576 2577 2578
  eNB_proc_t *proc       = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  int l;
2579

Raymond Knopp's avatar
Raymond Knopp committed
2580
  //  printf("fep0: slot %d\n",slot);
2581

2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592
  remove_7_5_kHz(eNB,(slot&1)+(proc->subframe_rx<<1));
  for (l=0; l<fp->symbols_per_tti/2; l++) {
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		(slot&1)+(proc->subframe_rx<<1),
		0,
		0
		);
  }
}
2593

2594

Raymond Knopp's avatar
Raymond Knopp committed
2595

2596 2597 2598 2599 2600 2601 2602
extern int oai_exit;

static void *fep_thread(void *param) {

  PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param;
  eNB_proc_t *proc  = &eNB->proc;
  while (!oai_exit) {
Raymond Knopp's avatar
Raymond Knopp committed
2603

2604 2605 2606
    if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break;  
    fep0(eNB,0);
    if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
Raymond Knopp's avatar
Raymond Knopp committed
2607 2608 2609 2610

    if (pthread_cond_signal(&proc->cond_fep) != 0) {
      printf("[eNB] ERROR pthread_cond_signal for fep thread exit\n");
      exit_fun( "ERROR pthread_cond_signal" );
2611
      return NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2612
    }
2613
  }
Raymond Knopp's avatar
Raymond Knopp committed
2614 2615 2616 2617 2618 2619



  return(NULL);
}

2620
void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) {
Raymond Knopp's avatar
Raymond Knopp committed
2621

2622
  eNB_proc_t *proc = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
2623

2624 2625 2626 2627 2628 2629
  proc->instance_cnt_fep         = -1;
    
  pthread_mutex_init( &proc->mutex_fep, NULL);
  pthread_cond_init( &proc->cond_fep, NULL);

  pthread_create(&proc->pthread_fep, attr_fep, fep_thread, (void*)eNB);
Raymond Knopp's avatar
Raymond Knopp committed
2630 2631


2632 2633
}

2634 2635 2636
extern void *td_thread(void*);

void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
2637 2638 2639

  eNB_proc_t *proc = &eNB->proc;

2640 2641
  proc->tdp.eNB = eNB;
  proc->instance_cnt_td         = -1;
2642
    
2643 2644
  pthread_mutex_init( &proc->mutex_td, NULL);
  pthread_cond_init( &proc->cond_td, NULL);
2645

2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663
  pthread_create(&proc->pthread_td, attr_td, td_thread, (void*)&proc->tdp);

}

extern void *te_thread(void*);

void init_te_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_te) {

  eNB_proc_t *proc = &eNB->proc;

  proc->tep.eNB = eNB;
  proc->instance_cnt_te         = -1;
    
  pthread_mutex_init( &proc->mutex_te, NULL);
  pthread_cond_init( &proc->cond_te, NULL);

  printf("Creating te_thread\n");
  pthread_create(&proc->pthread_te, attr_te, te_thread, (void*)&proc->tep);
2664 2665 2666

}

Raymond Knopp's avatar
Raymond Knopp committed
2667

2668
void eNB_fep_full_2thread(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2669 2670

  eNB_proc_t *proc = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
2671

2672
  struct timespec wait;
2673

2674 2675 2676 2677 2678 2679 2680
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
  start_meas(&eNB->ofdm_demod_stats);

  if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
2681
    printf("[eNB] ERROR pthread_mutex_lock for fep thread (IC %d)\n", proc->instance_cnt_fep);
2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694
    exit_fun( "error locking mutex_fep" );
    return;
  }

  if (proc->instance_cnt_fep==0) {
    printf("[eNB] FEP thread busy\n");
    exit_fun("FEP thread busy");
    pthread_mutex_unlock( &proc->mutex_fep );
    return;
  }
  
  ++proc->instance_cnt_fep;

2695

2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706
  if (pthread_cond_signal(&proc->cond_fep) != 0) {
    printf("[eNB] ERROR pthread_cond_signal for fep thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return;
  }
  
  pthread_mutex_unlock( &proc->mutex_fep );

  // call second slot in this symbol
  fep0(eNB,1);

Raymond Knopp's avatar
Raymond Knopp committed
2707
  wait_on_busy_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread");  
2708

2709
  stop_meas(&eNB->ofdm_demod_stats);
2710 2711
}

Raymond Knopp's avatar
Raymond Knopp committed
2712 2713


2714
void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2715

2716
  int l;
2717
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2718

2719
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
2720
  start_meas(&eNB->ofdm_demod_stats);
2721 2722
  remove_7_5_kHz(eNB,proc_rxtx->subframe_rx<<1);
  remove_7_5_kHz(eNB,1+(proc_rxtx->subframe_rx<<1));
2723 2724 2725 2726
  for (l=0; l<fp->symbols_per_tti/2; l++) {
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
2727
		(proc_rxtx->subframe_rx)<<1,
Raymond Knopp's avatar
Raymond Knopp committed
2728
		0,
2729 2730 2731 2732 2733
		0
		);
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
2734
		1+((proc_rxtx->subframe_rx)<<1),
2735 2736 2737 2738
		0,
		0
		);
  }
2739
  stop_meas(&eNB->ofdm_demod_stats);
2740 2741 2742 2743 2744
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
  
  if (eNB->node_function == NGFI_RRU_IF4p5) {
    /// **** send_IF4 of rxdataF to RCC (no prach now) **** ///
2745
    LOG_D(PHY,"send_IF4p5 (PULFFT): frame %d, subframe %d\n",proc_rxtx->frame_rx,proc_rxtx->subframe_rx);
2746
    send_IF4p5(eNB, proc_rxtx->frame_rx, proc_rxtx->subframe_rx, IF4p5_PULFFT, 0);
Raymond Knopp's avatar
Raymond Knopp committed
2747
  }    
2748 2749
}

2750
void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2751

Raymond Knopp's avatar
Raymond Knopp committed
2752
  eNB_proc_t *proc=&eNB->proc;
2753 2754 2755 2756 2757 2758 2759 2760 2761
  uint8_t seqno=0;

  /// **** send_IF5 of rxdata to BBU **** ///       
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );  
  send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );          

}

2762
void do_prach(PHY_VARS_eNB *eNB,int frame,int subframe) {
2763

Raymond Knopp's avatar
Raymond Knopp committed
2764
  eNB_proc_t *proc = &eNB->proc;
2765 2766 2767
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;

  // check if we have to detect PRACH first
2768
  if (is_prach_subframe(fp,frame,subframe)>0) { 
2769 2770 2771
    /* accept some delay in processing - up to 5ms */
    int i;
    for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) {
2772
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", frame,subframe,proc->instance_cnt_prach);
2773 2774 2775 2776 2777 2778 2779 2780 2781
      usleep(500);
    }
    if (proc->instance_cnt_prach == 0) {
      exit_fun( "PRACH thread busy" );
      return;
    }
    
    // wake up thread for PRACH RX
    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
Cedric Roux's avatar
Cedric Roux committed
2782
      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
2783 2784 2785 2786 2787 2788
      exit_fun( "error locking mutex_prach" );
      return;
    }
    
    ++proc->instance_cnt_prach;
    // set timing for prach thread
2789 2790
    proc->frame_prach = frame;
    proc->subframe_prach = subframe;
2791 2792 2793 2794 2795 2796 2797 2798 2799
    
    // the thread can now be woken up
    if (pthread_cond_signal(&proc->cond_prach) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index);
      exit_fun( "ERROR pthread_cond_signal" );
      return;
    }
    
    pthread_mutex_unlock( &proc->mutex_prach );
2800
  }
2801

2802
}
2803

2804
void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc){
2805 2806


2807
  //  eNB_proc_t *proc       = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
2808 2809 2810
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  const int subframe     = proc->subframe_rx;
  const int frame        = proc->frame_rx;
2811
  int offset             = (eNB->single_thread_flag==1) ? 0 : (subframe&1);
Sandeep Kumar's avatar
Sandeep Kumar committed
2812

Raymond Knopp's avatar
Raymond Knopp committed
2813 2814
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB+offset, proc->frame_rx );
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+offset, proc->subframe_rx );
2815

Raymond Knopp's avatar
Raymond Knopp committed
2816 2817 2818 2819 2820 2821 2822 2823
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) {

    if (eNB->node_function == NGFI_RRU_IF4p5) {
      /// **** in TDD during DL send_IF4 of ULTICK to RCC **** ///
      send_IF4p5(eNB, proc->frame_rx, proc->subframe_rx, IF4p5_PULTICK, 0);
    }    
    return;
  }
2824

2825 2826

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 1 ); 
2827
  start_meas(&eNB->phy_proc_rx);
2828
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe);
2829

Raymond Knopp's avatar
Raymond Knopp committed
2830

2831
  if (eNB->fep) eNB->fep(eNB,proc);
2832

Raymond Knopp's avatar
Raymond Knopp committed
2833
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 0 );
2834 2835
}

2836

2837
void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type)
2838
{
2839
  //RX processing for ue-specific resources (i
2840
  UNUSED(r_type);
2841
  uint32_t ret=0,i,j,k;
2842 2843 2844 2845 2846
  uint32_t harq_pid, harq_idx, round;
  uint8_t nPRS;
  int sync_pos;
  uint16_t rnti=0;
  uint8_t access_mode;
2847
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2848

2849
  const int subframe = proc->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
2850
  const int frame    = proc->frame_rx;
2851
  int offset         = eNB->CC_id;//(proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1;
2852

2853

2854
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return;
2855

Raymond Knopp's avatar
Raymond Knopp committed
2856
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
2857

2858
#ifdef DEBUG_PHY_PROC
2859
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe);
Lionel Gauthier's avatar
Lionel Gauthier committed
2860
#endif
2861

2862
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
2863

2864
  T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
Cedric Roux's avatar
Cedric Roux committed
2865
    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
2866
             eNB->frame_parms.samples_per_tti * 4));
2867

2868 2869 2870 2871
  eNB->rb_mask_ul[0]=0;
  eNB->rb_mask_ul[1]=0;
  eNB->rb_mask_ul[2]=0;
  eNB->rb_mask_ul[3]=0;
2872

2873 2874


2875
  // Check for active processes in current subframe
2876
  harq_pid = subframe2harq_pid(fp,
2877
                               frame,subframe);
2878

2879 2880
  // reset the cba flag used for collision detection
  for (i=0; i < NUM_MAX_CBA_GROUP; i++) {
2881
    eNB->cba_last_reception[i]=0;
2882
  }
2883

2884
  // Do PUCCH processing first
2885

2886
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2887
    pucch_procedures(eNB,proc,i,harq_pid);
2888
  }
2889

2890
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2891

2892
    // check for Msg3
2893
    if (eNB->mac_enabled==1) {
2894
      if (eNB->UE_stats[i].mode == RA_RESPONSE) {
2895
	process_Msg3(eNB,proc,i,harq_pid);
2896 2897
      }
    }
2898 2899


2900 2901 2902
    eNB->pusch_stats_rb[i][(frame*10)+subframe] = -63;
    eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
    eNB->pusch_stats_mcs[i][(frame*10)+subframe] = -63;
2903

2904 2905 2906
    if ((eNB->ulsch[i]) &&
        (eNB->ulsch[i]->rnti>0) &&
        (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) {
2907
      // UE is has ULSCH scheduling
2908
      round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
2909
 
2910
      for (int rb=0;
2911
           rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
2912
	   rb++) {
2913
	int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
2914
	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
2915
      }
2916 2917


2918
      if (eNB->ulsch[i]->Msg3_flag == 1) {
2919
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
2920
              eNB->Mod_id,
2921 2922
              frame,
              subframe,
2923
              eNB->UE_stats[i].sector);
2924 2925
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1);
      } else {
2926

2927
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n",
2928
              eNB->Mod_id,
2929 2930 2931
              frame,
              subframe,
              i,
2932
              mode_string[eNB->UE_stats[i].mode]);
2933
      }
2934

2935

2936
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
2937

2938
      eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
2939
				    nPRS)%12;
2940

2941
      if (fp->frame_type == FDD ) {
2942
        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
2943

2944 2945
        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
2946
        } else {
2947
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
2948
        }
2949
      }
2950

2951 2952
      LOG_D(PHY,
            "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, mcs %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, nprs %d), O_ACK %d \n",
2953
            eNB->Mod_id,harq_pid,frame,subframe,
2954 2955 2956 2957 2958 2959 2960 2961 2962 2963
            eNB->ulsch[i]->harq_processes[harq_pid]->dci_alloc,
            eNB->ulsch[i]->harq_processes[harq_pid]->rar_alloc,
            eNB->ulsch[i]->harq_processes[harq_pid]->round,
            eNB->ulsch[i]->harq_processes[harq_pid]->first_rb,
            eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb,
            eNB->ulsch[i]->harq_processes[harq_pid]->mcs,
            eNB->ulsch[i]->harq_processes[harq_pid]->TBS,
            eNB->ulsch[i]->harq_processes[harq_pid]->rvidx,
            eNB->ulsch[i]->cyclicShift,
            eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2,
2964
            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
2965
            nPRS,
2966 2967 2968 2969
            eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK);
      eNB->pusch_stats_rb[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
      eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->round;
      eNB->pusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->mcs;
2970
      start_meas(&eNB->ulsch_demodulation_stats);
2971

2972
      if (eNB->abstraction_flag==0) {
2973
        rx_ulsch(eNB,proc,
2974
                 eNB->UE_stats[i].sector,  // this is the effective sector id
2975
                 i,
2976
                 eNB->ulsch,
2977 2978
                 0);
      }
2979

2980 2981
#ifdef PHY_ABSTRACTION
      else {
2982
        rx_ulsch_emul(eNB,proc,
2983
                      eNB->UE_stats[i].sector,  // this is the effective sector id
2984 2985
                      i);
      }
2986 2987

#endif
2988
      stop_meas(&eNB->ulsch_demodulation_stats);
2989

2990

2991
      start_meas(&eNB->ulsch_decoding_stats);
2992

2993
      if (eNB->abstraction_flag == 0) {
2994
        ret = ulsch_decoding(eNB,proc,
2995 2996
                             i,
                             0, // control_only_flag
2997 2998
                             eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
			     eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2999
      }
3000

3001
#ifdef PHY_ABSTRACTION
3002
      else {
3003 3004
        ret = ulsch_decoding_emul(eNB,
				  proc,
3005 3006 3007
                                  i,
                                  &rnti);
      }
3008

3009
#endif
3010
      stop_meas(&eNB->ulsch_decoding_stats);
3011

3012
      LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n",
3013
            eNB->Mod_id,harq_pid,
3014
            frame,subframe,
3015 3016 3017 3018 3019 3020 3021 3022 3023
            eNB->ulsch[i]->rnti,
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
            eNB->UE_stats[i].UL_rssi[0],
            eNB->UE_stats[i].UL_rssi[1],
            eNB->measurements->n0_power_dB[0],
            eNB->measurements->n0_power_dB[1],
            eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
            eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
3024
            ret);
3025

3026
      //compute the expected ULSCH RX power (for the stats)
3027
      eNB->ulsch[(uint32_t)i]->harq_processes[harq_pid]->delta_TF =
3028
        get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
3029

3030
      eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
3031 3032
#ifdef DEBUG_PHY_PROC
      LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d Clearing subframe_scheduling_flag\n",
3033
            eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
3034
#endif
3035
      eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
3036

3037
      if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) {
3038
#ifdef DEBUG_PHY_PROC
3039
        //if (((frame%10) == 0) || (frame < 50))
3040
        print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
3041
#endif
3042 3043 3044
        extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
                    eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
                    &eNB->UE_stats[i],
3045
                    fp->N_RB_DL,
3046
                    &rnti, &access_mode);
3047
        eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
3048

3049
      }
3050

3051
      if (eNB->ulsch[i]->Msg3_flag == 1)
3052
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
3053

3054
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
3055
        T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(eNB->ulsch[i]->rnti),
3056
          T_INT(harq_pid));
3057

3058 3059 3060 3061
        eNB->UE_stats[i].ulsch_round_errors[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
        eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
        eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 0;
        eNB->ulsch[i]->harq_processes[harq_pid]->round++;
3062

3063
        LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->round);
3064

3065
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3066

3067
          LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
3068 3069
                eNB->Mod_id,
                eNB->CC_id,
3070
                frame,subframe, i,
3071
                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
3072
                fp->maxHARQ_Msg3Tx-1);
3073 3074
	  /*dump_ulsch(eNB,proc,i);
	    exit(-1);*/
3075

3076
	  LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n",
3077
		eNB->Mod_id,harq_pid,
3078
		frame,subframe,
3079 3080 3081 3082 3083 3084 3085 3086 3087
		eNB->ulsch[i]->rnti,
		dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
		dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
		eNB->UE_stats[i].UL_rssi[0],
		eNB->UE_stats[i].UL_rssi[1],
		eNB->measurements->n0_power_dB[0],
		eNB->measurements->n0_power_dB[1],
		eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
		eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
3088
		ret);
3089

3090
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round ==
3091
              fp->maxHARQ_Msg3Tx) {
3092
            LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n",
3093
                  eNB->Mod_id, i);
3094
            eNB->UE_stats[i].mode = PRACH;
3095 3096 3097
	    if (eNB->mac_enabled==1) {
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3098
					frame,
3099
					eNB->UE_stats[i].crnti);
3100
	    }
3101
            mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
3102

3103 3104
            eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
            //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0;
3105 3106

          } else {
3107
            // activate retransmission for Msg3 (signalled to UE PHY by PHICH (not MAC/DCI)
3108
            eNB->ulsch[(uint32_t)i]->Msg3_active = 1;
3109

3110
            get_Msg3_alloc_ret(fp,
3111
                               subframe,
3112
                               frame,
3113 3114
                               &eNB->ulsch[i]->Msg3_frame,
                               &eNB->ulsch[i]->Msg3_subframe);
Cedric Roux's avatar
Cedric Roux committed
3115

3116 3117 3118
            mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, eNB->ulsch[i]->rnti,
                                         eNB->ulsch[i]->Msg3_frame, eNB->ulsch[i]->Msg3_subframe);

Cedric Roux's avatar
Cedric Roux committed
3119 3120 3121
            T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
              T_INT(i), T_INT(eNB->ulsch[i]->rnti), T_INT(0 /* 0 is for retransmission*/),
              T_INT(eNB->ulsch[i]->Msg3_frame), T_INT(eNB->ulsch[i]->Msg3_subframe));
3122
          }
3123 3124
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
3125

3126 3127
        else { //normal ULSCH
          LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n",
3128
                eNB->Mod_id,harq_pid,
3129
                frame,subframe, i,
3130 3131 3132 3133
                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
                eNB->ulsch[i]->Mlimit,
                eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
                eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1]);
3134 3135 3136

#if defined(MESSAGE_CHART_GENERATOR_PHY)
          MSC_LOG_RX_DISCARDED_MESSAGE(
3137 3138 3139 3140 3141 3142 3143
				       MSC_PHY_ENB,MSC_PHY_UE,
				       NULL,0,
				       "%05u:%02u ULSCH received rnti %x harq id %u round %d",
				       frame,subframe,
				       eNB->ulsch[i]->rnti,harq_pid,
				       eNB->ulsch[i]->harq_processes[harq_pid]->round-1
				       );
3144
#endif
3145

3146
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) {
3147
            LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
3148
                  eNB->Mod_id,harq_pid,
3149
                  frame,subframe, i,
3150
                  eNB->ulsch[i]->Mlimit);
3151

3152 3153 3154 3155
            eNB->ulsch[i]->harq_processes[harq_pid]->round=0;
            eNB->ulsch[i]->harq_processes[harq_pid]->phich_active=0;
            eNB->UE_stats[i].ulsch_errors[harq_pid]++;
            eNB->UE_stats[i].ulsch_consecutive_errors++;
3156

Younes's avatar
Younes committed
3157 3158 3159 3160
	   /*if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
		dump_ulsch(eNB,proc,i);
	 	exit(-1);
           }*/
3161
	    // indicate error to MAC
3162 3163 3164 3165 3166 3167 3168 3169 3170
	    if (eNB->mac_enabled == 1)
	      mac_xface->rx_sdu(eNB->Mod_id,
				eNB->CC_id,
				frame,subframe,
				eNB->ulsch[i]->rnti,
				NULL,
				0,
				harq_pid,
				&eNB->ulsch[i]->Msg3_flag);
3171 3172 3173 3174
          }
        }
      }  // ulsch in error
      else {
3175 3176 3177



3178
        T(T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(eNB->ulsch[i]->rnti),
3179 3180
          T_INT(harq_pid));

3181
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3182
	  LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
3183
		eNB->Mod_id,harq_pid,
3184 3185
		frame,subframe);
	  LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n",
3186
		eNB->Mod_id,harq_pid,
3187
		frame,subframe,
3188 3189 3190 3191 3192 3193 3194 3195 3196
		eNB->ulsch[i]->rnti,
		dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
		dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
		eNB->UE_stats[i].UL_rssi[0],
		eNB->UE_stats[i].UL_rssi[1],
		eNB->measurements->n0_power_dB[0],
		eNB->measurements->n0_power_dB[1],
		eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
		eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
3197 3198 3199 3200
		ret);
	}
#if defined(MESSAGE_CHART_GENERATOR_PHY)
        MSC_LOG_RX_MESSAGE(
3201 3202 3203 3204 3205 3206
			   MSC_PHY_ENB,MSC_PHY_UE,
			   NULL,0,
			   "%05u:%02u ULSCH received rnti %x harq id %u",
			   frame,subframe,
			   eNB->ulsch[i]->rnti,harq_pid
			   );
3207
#endif
3208
        for (j=0; j<fp->nb_antennas_rx; j++)
3209
          //this is the RSSI per RB
3210
          eNB->UE_stats[i].UL_rssi[j] =
3211
	    
3212 3213
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
                     (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
3214
                     fp->ofdm_symbol_size) -
3215 3216
            eNB->rx_total_gain_dB -
            hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
3217
            get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
3218
	    
3219 3220 3221 3222
        eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
        eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1;
        eNB->ulsch[i]->harq_processes[harq_pid]->round = 0;
        eNB->UE_stats[i].ulsch_consecutive_errors = 0;
3223

3224
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3225
	  if (eNB->mac_enabled==1) {
3226

3227
	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
3228
		  eNB->Mod_id,
3229
		  frame,harq_pid,i);
3230 3231 3232 3233 3234 3235 3236 3237 3238
	    if (eNB->mac_enabled)
	      mac_xface->rx_sdu(eNB->Mod_id,
				eNB->CC_id,
				frame,subframe,
				eNB->ulsch[i]->rnti,
				eNB->ulsch[i]->harq_processes[harq_pid]->b,
				eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
				harq_pid,
				&eNB->ulsch[i]->Msg3_flag);
3239 3240
	    
	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
3241 3242
	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	      eNB->UE_stats[i].mode = PRACH;
3243 3244
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3245
					frame,
3246 3247 3248
					eNB->UE_stats[i].crnti);
	      mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
	      eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
3249 3250 3251
	    } // Msg3_flag == 0
	    
	  } // mac_enabled==1
3252

3253 3254
          eNB->UE_stats[i].mode = PUSCH;
          eNB->ulsch[i]->Msg3_flag = 0;
3255

3256
	  LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",eNB->Mod_id,frame,subframe,i);
3257

3258
          for (k=0; k<8; k++) { //harq_processes
3259 3260 3261 3262
            for (j=0; j<eNB->dlsch[i][0]->Mlimit; j++) {
              eNB->UE_stats[i].dlsch_NAK[k][j]=0;
              eNB->UE_stats[i].dlsch_ACK[k][j]=0;
              eNB->UE_stats[i].dlsch_trials[k][j]=0;
3263
            }
3264

3265 3266 3267
            eNB->UE_stats[i].dlsch_l2_errors[k]=0;
            eNB->UE_stats[i].ulsch_errors[k]=0;
            eNB->UE_stats[i].ulsch_consecutive_errors=0;
3268

3269 3270 3271 3272 3273
            for (j=0; j<eNB->ulsch[i]->Mlimit; j++) {
              eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0;
              eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
              eNB->UE_stats[i].ulsch_round_errors[k][j]=0;
              eNB->UE_stats[i].ulsch_round_fer[k][j]=0;
3274
            }
3275 3276
          }

3277 3278 3279
          eNB->UE_stats[i].dlsch_sliding_cnt=0;
          eNB->UE_stats[i].dlsch_NAK_round0=0;
          eNB->UE_stats[i].dlsch_mcs_offset=0;
3280 3281 3282
        } // Msg3_flag==1
	else {  // Msg3_flag == 0

3283
#ifdef DEBUG_PHY_PROC
3284 3285
#ifdef DEBUG_ULSCH
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
3286
                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
3287

3288 3289
          for (j=0; j<eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3; j++)
            LOG_T(PHY,"%x.",eNB->ulsch[i]->harq_processes[harq_pid]->b[j]);
3290 3291 3292

          LOG_T(PHY,"\n");
#endif
3293
#endif
3294

3295
	  if (eNB->mac_enabled==1) {
3296

3297 3298
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
3299
			      frame,subframe,
3300 3301 3302
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
3303 3304
			      harq_pid,
			      NULL);
3305

3306
#ifdef LOCALIZATION
3307 3308
	    start_meas(&eNB->localization_stats);
	    aggregate_eNB_UE_localization_stats(eNB,
3309 3310 3311
						i,
						frame,
						subframe,
3312 3313
						get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
	    stop_meas(&eNB->localization_stats);
3314
#endif
3315 3316 3317
	    
	  } // mac_enabled==1
        } // Msg3_flag == 0
3318

3319
        // estimate timing advance for MAC
3320
        if (eNB->abstraction_flag == 0) {
3321
          sync_pos = lte_est_timing_advance_pusch(eNB,i);
3322
          eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
3323
        }
3324

3325 3326
#ifdef DEBUG_PHY_PROC
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
3327
              eNB->Mod_id,
3328 3329
              frame, subframe,
              i,
3330
              eNB->UE_stats[i].timing_advance_update);
3331
#endif
3332 3333


3334 3335 3336
      }  // ulsch not in error

      // process HARQ feedback
3337
#ifdef DEBUG_PHY_PROC
3338
      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
3339
            eNB->dlsch[i][0]->rnti,
3340 3341
            frame,subframe,
            i);
3342
#endif
3343
      process_HARQ_feedback(i,
3344
                            eNB,proc,
3345 3346 3347 3348 3349 3350 3351
                            1, // pusch_flag
                            0,
                            0,
                            0);

#ifdef DEBUG_PHY_PROC
      LOG_D(PHY,"[eNB %d] Frame %d subframe %d, sect %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n",
3352
            eNB->Mod_id,frame,subframe,
3353
            eNB->UE_stats[i].sector,
3354 3355 3356
            harq_pid,
            i,
            ret,
3357 3358 3359 3360 3361
            eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status,
            eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
            eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
            eNB->UE_stats[i].ulsch_errors[harq_pid],
            eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]);
3362 3363 3364 3365
#endif
      
      // dump stats to VCD
      if (i==0) {
3366 3367 3368
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS0+harq_pid,eNB->pusch_stats_mcs[0][(frame*10)+subframe]);
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB0+harq_pid,eNB->pusch_stats_rb[0][(frame*10)+subframe]);
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND0+harq_pid,eNB->pusch_stats_round[0][(frame*10)+subframe]);
3369
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
3370 3371
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES0+harq_pid,ret);
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN0+harq_pid,(frame*10)+subframe);
Lionel Gauthier's avatar
Lionel Gauthier committed
3372
      }
3373
    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
3374 3375


3376
    // update ULSCH statistics for tracing
3377
    if ((frame % 100 == 0) && (subframe == 4)) {
3378
      for (harq_idx=0; harq_idx<8; harq_idx++) {
3379 3380 3381 3382 3383 3384 3385 3386
        for (round=0; round<eNB->ulsch[i]->Mlimit; round++) {
          if ((eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round] -
               eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]) != 0) {
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] =
              (100*(eNB->UE_stats[i].ulsch_round_errors[harq_idx][round] -
                    eNB->UE_stats[i].ulsch_round_errors_last[harq_idx][round]))/
              (eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round] -
               eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]);
3387
          } else {
3388
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
3389 3390
          }

3391 3392 3393 3394
          eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round] =
            eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round];
          eNB->UE_stats[i].ulsch_round_errors_last[harq_idx][round] =
            eNB->UE_stats[i].ulsch_round_errors[harq_idx][round];
3395
        }
3396 3397
      }
    }
3398

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3399
    if ((frame % 100 == 0) && (subframe==4)) {
3400
      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
3401
					eNB->UE_stats[i].total_TBS_last);
3402

3403
      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
3404
    }
3405

3406
    // CBA (non-LTE)
3407
    cba_procedures(eNB,proc,i,harq_pid);
3408 3409
  } // loop i=0 ... NUMBER_OF_UE_MAX-1

3410
  if (eNB->abstraction_flag == 0) {
3411
    lte_eNB_I0_measurements(eNB,
3412 3413
			    subframe,
			    0,
3414 3415
			    eNB->first_run_I0_measurements);
    eNB->first_run_I0_measurements = 0;
3416
  }
3417

3418
#ifdef PHY_ABSTRACTION
3419 3420 3421 3422
  else {
    lte_eNB_I0_measurements_emul(eNB,
				 0);
  }
3423

3424
#endif
3425
  //}
3426 3427

#ifdef EMOS
3428
  phy_procedures_emos_eNB_RX(subframe,eNB);
3429 3430
#endif

3431 3432 3433 3434 3435 3436 3437 3438 3439
#if defined(FLEXRAN_AGENT_SB_IF)
#ifndef DISABLE_SF_TRIGGER
  //Send subframe trigger to the controller
  if (mac_agent_registered[eNB->Mod_id]) {
    agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
  }
#endif
#endif

Raymond Knopp's avatar
Raymond Knopp committed
3440
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
3441

3442
  stop_meas(&eNB->phy_proc_rx);
3443

3444 3445 3446 3447
}

#undef DEBUG_PHY_PROC

3448 3449 3450 3451
#ifdef Rel10
int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type)
{

3452
  int do_proc=0;// do nothing
3453 3454

  switch(r_type) {
3455
  case no_relay:
3456
    do_proc= no_relay; // perform the normal eNB operation
3457
    break;
3458

3459
  case multicast_relay:
3460
    if (((next_slot >>1) < 6) || ((next_slot >>1) > 8))
3461
      do_proc = 0; // do nothing
3462 3463 3464
    else // SF#6, SF#7 and SF#8
      do_proc = multicast_relay; // do PHY procedures eNB TX

3465
    break;
3466

3467 3468
  default: // should'not be here
    LOG_W(PHY,"Not supported relay type %d, do nothing\n", r_type);
3469
    do_proc=0;
3470 3471
    break;
  }
3472

3473 3474
  return do_proc;
}
3475
#endif