phy_procedures_lte_eNb.c 105 KB
Newer Older
Raymond Knopp's avatar
Raymond Knopp committed
1

2
/*******************************************************************************
3
    OpenAirInterface
ghaddab's avatar
ghaddab committed
4
    Copyright(c) 1999 - 2014 Eurecom
5

ghaddab's avatar
ghaddab committed
6 7 8 9
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
10 11


ghaddab's avatar
ghaddab committed
12 13 14 15
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
16

ghaddab's avatar
ghaddab committed
17
    You should have received a copy of the GNU General Public License
18 19
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
ghaddab's avatar
ghaddab committed
20
   see <http://www.gnu.org/licenses/>.
21 22

  Contact Information
ghaddab's avatar
ghaddab committed
23 24
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
25
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
26

ghaddab's avatar
ghaddab committed
27
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
28

29
*******************************************************************************/
30 31 32

/*! \file phy_procedures_lte_eNB.c
 * \brief Implementation of eNB procedures from 36.213 LTE specifications
33
 * \author R. Knopp, F. Kaltenberger, N. Nikaein
34 35 36
 * \date 2011
 * \version 0.1
 * \company Eurecom
37
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr
38 39 40 41 42 43 44 45 46
 * \note
 * \warning
 */

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

47
#include "PHY/LTE_TRANSPORT/if4_tools.h"
Sandeep Kumar's avatar
Sandeep Kumar committed
48
#include "PHY/LTE_TRANSPORT/if5_tools.h"
49

50 51 52 53
#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif

54
//#define DEBUG_PHY_PROC (Already defined in cmake)
55 56 57 58 59 60 61
//#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"

62 63
#include "T.h"

64
#include "assertions.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
65
#include "msc.h"
66

67 68
#include <time.h>

69
#if defined(ENABLE_ITTI)
Lionel Gauthier's avatar
Lionel Gauthier committed
70
#   include "intertask_interface.h"
71 72
#endif

73 74 75 76 77 78
//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

79 80
void exit_fun(const char* s);

81 82
extern int exit_openair;

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

86 87 88
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)));
89 90
int *eNB_sync_buffer[2] = {eNB_sync_buffer0, eNB_sync_buffer1};

91
extern uint16_t hundred_times_log10_NPRB[100];
92

93
unsigned int max_peak_val;
94
int max_sync_pos;
95 96 97 98 99 100 101

//DCI_ALLOC_t dci_alloc[8];

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

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

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

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

115 116
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
117

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

122 123
  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)
124
      return(1);
125 126
  } 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))
127
      return(1);
128 129
  } 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))
130
      return(1);
131 132
  } 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))
133
      return(1);
134 135
  } 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))
136
      return(1);
137 138 139 140
  }

  return(0);
}
141

142

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

147 148

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

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

166 167 168
	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));
169
	LOG_D(PHY,"Initializing Po_PUCCH: p0_NominalPUCCH %d, gain %d => %d\n",
170 171 172
	      eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH,
	      eNB->rx_total_gain_dB,
	      eNB->UE_stats[i].Po_PUCCH);
173
  
174
        return(i);
175
      }
176
    }
177 178 179 180
  }
  return(-1);
}

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

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
187
    eNB = PHY_vars_eNB_g[Mod_idP][CC_id];
188
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
189
      if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) {
190 191 192 193
	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 {
194
	if (eNB->UE_stats[i].crnti==rntiP) {
195
	  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Removed ue %"PRIx16" ", rntiP);
196 197 198

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

199
	  //LOG_D(PHY,("[PHY] UE_id %d\n",i);
200 201 202 203
	  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));
204 205
	  //  mac_exit_wrapper("Removing UE");
	  
206

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

216
int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
217
{
218
  uint8_t i;
219

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

230 231 232
  return(-1);
}

Lionel Gauthier's avatar
Lionel Gauthier committed
233
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 ul_flag)
234 235 236 237
{
  LTE_eNB_DLSCH_t *DLSCH_ptr;
  LTE_eNB_ULSCH_t *ULSCH_ptr;
  uint8_t ulsch_subframe,ulsch_frame;
238
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
239
  int8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]);
240 241

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

  if (ul_flag == 0)  {// this is a DL request
248
    DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[(uint32_t)UE_id][0];
249

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

253 254 255 256 257
    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;
258
      *round = 0;
259 260 261
    } else {
      printf("%s:%d: bad state for harq process - PLEASE REPORT!!\n", __FILE__, __LINE__);
      abort();
262
    }
263
  } else { // This is a UL request
264

265 266 267
    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);
268
    // Note this is for TDD configuration 3,4,5 only
269
    *harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,
270 271
                                  ulsch_frame,
                                  ulsch_subframe);
272
    *round    = ULSCH_ptr->harq_processes[*harq_pid]->round;
273
    LOG_T(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Checking HARQ, round %d\n",Mod_id,*harq_pid,frame,subframe,*round);
274
  }
275

276 277 278
  return(0);
}

279
int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
280
{
281
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
282 283
}

284 285
int16_t get_target_pucch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
{
286
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
287 288
}

289
#ifdef EMOS
290
void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB)
291
{
292 293 294 295 296 297

}
#endif



298
void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type)
299 300
{
  UNUSED(r_type);
301
  int subframe = proc->subframe_rx;
302

303
#ifdef DEBUG_PHY_PROC
304
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", eNB->Mod_id,proc->frame_rx, subframe);
305
#endif
306

307

Raymond Knopp's avatar
 
Raymond Knopp committed
308
  if (abstraction_flag == 0) {
309
    lte_eNB_I0_measurements(eNB,
310
			    subframe,
311
                            0,
312
                            eNB->first_run_I0_measurements);
Raymond Knopp's avatar
 
Raymond Knopp committed
313
  }
314

315
#ifdef PHY_ABSTRACTION
Raymond Knopp's avatar
 
Raymond Knopp committed
316
  else {
317
    lte_eNB_I0_measurements_emul(eNB,
318
                                 0);
319
  }
320

Raymond Knopp's avatar
 
Raymond Knopp committed
321 322
#endif

323

324 325
}

Raymond Knopp's avatar
 
Raymond Knopp committed
326 327


328
#ifdef EMOS
329
void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *eNB)
330 331
{

332 333
  uint8_t aa;
  uint16_t last_subframe_emos;
334
  uint16_t pilot_pos1 = 3 - eNB->frame_parms.Ncp, pilot_pos2 = 10 - 2*eNB->frame_parms.Ncp;
335
  uint32_t bytes;
336 337 338

  last_subframe_emos=0;

Raymond Knopp's avatar
 
Raymond Knopp committed
339

Raymond Knopp's avatar
 
Raymond Knopp committed
340

Raymond Knopp's avatar
 
Raymond Knopp committed
341

342
#ifdef EMOS_CHANNEL
343

344
  //if (last_slot%2==1) // this is for all UL subframes
345
  if (subframe==3)
346 347 348 349 350 351 352
    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));
353
    }
354

355 356
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
357
  if (subframe==4) {
358
    emos_dump_eNB.timestamp = rt_get_time_ns();
359 360 361 362 363
    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],
364
           sizeof(PHY_MEASUREMENTS_eNB));
365
    memcpy(&emos_dump_eNB.UE_stats[0],&eNB->UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats));
366 367

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

369 370
    //bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, "test", sizeof("test"));
    if (bytes!=sizeof(fifo_dump_emos_eNB)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
371
      LOG_W(PHY,"[eNB %d] Frame %d, subframe %d, Problem writing EMOS data to FIFO (bytes=%d, size=%d)\n",
372
            eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, subframe,bytes,sizeof(fifo_dump_emos_eNB));
373
    } else {
374
      if (eNB->proc[(subframe+1)%10].frame_tx%100==0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
375
        LOG_I(PHY,"[eNB %d] Frame %d (%d), subframe %d, Writing %d bytes EMOS data to FIFO\n",
376
              eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, ((fifo_dump_emos_eNB*)&emos_dump_eNB)->frame_tx, subframe, bytes);
377
      }
378
    }
379 380 381 382 383 384 385
  }
}
#endif


#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
#define AMP_OVER_2 (AMP>>1)
386 387
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)};
388

Lionel Gauthier's avatar
Lionel Gauthier committed
389

Raymond Knopp's avatar
 
Raymond Knopp committed
390

Cedric Roux's avatar
Cedric Roux committed
391
unsigned int taus(void);
392
DCI_PDU DCI_pdu_tmp;
Raymond Knopp's avatar
 
Raymond Knopp committed
393

Raymond Knopp's avatar
 
Raymond Knopp committed
394

395
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) {
396

Raymond Knopp's avatar
 
Raymond Knopp committed
397

398
#ifdef Rel10
399 400
  MCH_PDU *mch_pduP;
  MCH_PDU  mch_pdu;
401
  //  uint8_t sync_area=255;
402
#endif
403

404
  int subframe = proc->subframe_tx;
405

Raymond Knopp's avatar
 
Raymond Knopp committed
406
  if (abstraction_flag==0) {
407 408
    // This is DL-Cell spec pilots in Control region
    generate_pilots_slot(eNB,
409
			 eNB->common_vars.txdataF[0],
410 411
			 AMP,
			 subframe<<1,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
412
  }
413
  
414
#ifdef Rel10
415 416 417 418
  // 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,
419
				    proc->frame_tx,
420 421 422 423 424 425
				    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",
426 427
	    eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs,
	    eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
428 429
    else {
      LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n",
430
	    eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->sync_area,
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
	    (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment");
      mch_pduP = NULL;
    }
    
    break;
    
  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
452
    } else {
453
      mch_pduP=NULL;
454
    }
455 456 457 458 459 460
    
    rn->mch_avtive[subframe]=0;
    break;
    
  default:
    LOG_W(PHY,"[eNB %"PRIu8"] Frame %d subframe %d: unknown relaying type %d \n",
461
	  eNB->Mod_id,proc->frame_tx,subframe,r_type);
462 463 464 465 466 467 468
    mch_pduP=NULL;
    break;
  }// switch
  
  if (mch_pduP) {
    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0, abstraction_flag);
    // Generate PMCH
469
    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload,abstraction_flag);
470
  } else {
471
    LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
472
  }
473 474 475
  
#endif
}
476

477
void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstraction_flag) {
478

479 480
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int **txdataF = eNB->common_vars.txdataF[0];
481
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
482 483
  int subframe = proc->subframe_tx;
  int frame = proc->frame_tx;
484

485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
  // generate Cell-Specific Reference Signals for both slots
  if (abstraction_flag==0) {
    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);
  }    
Raymond Knopp's avatar
 
Raymond Knopp committed
501

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

596
    /// generate PBCH
Raymond Knopp's avatar
 
Raymond Knopp committed
597
    if (abstraction_flag==0) {
598
      generate_pbch(&eNB->pbch,
599 600 601 602
                    txdataF,
                    AMP,
                    fp,
                    pbch_pdu,
603
                    frame&3);
604 605 606 607 608 609
    }
#ifdef PHY_ABSTRACTION
    else {
      generate_pbch_emul(eNB,pbch_pdu);
    }
#endif
610

611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
  }
  else if ((subframe == 1) &&
	   (fp->frame_type == TDD)&&
	   (abstraction_flag==0)) {
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
  }
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
	   (fp->frame_type == FDD) &&
	   (abstraction_flag==0)) {
626 627 628 629 630 631 632 633 634 635
    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);
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662

  }

  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
	   (fp->frame_type == TDD) &&
	   (abstraction_flag==0)) {
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
  }

  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
	   (fp->frame_type == TDD) &&
	   (abstraction_flag==0)) {
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }

}

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

665
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
666 667
  int frame = proc->frame_tx;
  int subframe = proc->subframe_tx;
668 669 670 671 672 673 674 675 676

  // 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,
677
				       &eNB->dlsch_SI,
678 679 680 681 682
				       fp,
				       eNB->pdsch_config_dedicated,
				       SI_RNTI,
				       0,
				       P_RNTI,
683
				       eNB->UE_stats[0].DL_pmi_single);
684 685
    
    
686
    eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE;
687
    
688
    LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
689
	  eNB->dlsch_SI->nCCE[subframe]);
690 691 692 693
    
#if defined(SMBV) 
    
    // configure SI DCI
694 695
    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);
696 697 698 699 700 701 702 703 704 705 706 707 708 709
      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,
710
				       &eNB->dlsch_ra,
711 712 713 714 715
				       fp,
				       eNB->pdsch_config_dedicated,
				       SI_RNTI,
				       dci_alloc->rnti,
				       P_RNTI,
716
				       eNB->UE_stats[0].DL_pmi_single);
717 718
    
    
719
    eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE;
720
    
721
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
722
	  eNB->dlsch_ra->nCCE[subframe]);
723 724 725
#if defined(SMBV) 
    
    // configure RA DCI
726 727
    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);
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
      smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", dci_alloc, i);
    }
    
#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
    

    
    if (UE_id>=0) {
#if defined(SMBV) 
      // Configure this user
745 746
      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,
747 748 749 750 751 752 753 754 755 756 757 758
              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);
      }
      
#endif

      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,
759
					 eNB->dlsch[(uint8_t)UE_id],
760 761 762 763 764
					 fp,
					 eNB->pdsch_config_dedicated,
					 SI_RNTI,
					 0,
					 P_RNTI,
765
					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single);
766
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
767
	    eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
768 769
      
      
770
      eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
771
      
772
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"/%u\n",eNB->Mod_id,frame,subframe,
773
	    dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]);
774 775 776 777
      
#if defined(SMBV) 
      
      // configure UE-spec DCI
778 779
      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);
780
	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
781
      }
782 783 784 785 786
      
#endif
      
      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,
787
	    frame, subframe,UE_id,
788 789 790 791
	    dci_alloc->format,
	    1<<dci_alloc->L);
    } else {
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n",
792
	    eNB->Mod_id,frame,dci_alloc->rnti);
Raymond Knopp's avatar
 
Raymond Knopp committed
793
    }
794 795 796
  }
  
}
797

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

800
  int harq_pid;
801
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
802
  int frame = proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
803
  int subframe = proc->subframe_tx;
804

805
  LOG_D(PHY,
806 807 808
	"[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,
809
			  pdcch_alloc2ul_frame(fp,frame,subframe),
810
			  pdcch_alloc2ul_subframe(fp,subframe)),
811
	frame,
812
	subframe,
813
	pdcch_alloc2ul_frame(fp,frame,subframe),
814 815 816 817 818
	pdcch_alloc2ul_subframe(fp,subframe),
	dci_alloc->rnti,
	dci_alloc->dci_pdu[0],
	1<<dci_alloc->L);
  
819
  generate_eNB_ulsch_params_from_dci(eNB,
820
				     proc,
821
				     &dci_alloc->dci_pdu[0],
822 823 824 825 826 827 828 829 830 831
				     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",
832
	eNB->Mod_id,frame,subframe,dci_alloc->rnti,
833 834 835 836 837
	dci_alloc->firstCCE);
  
#if defined(SMBV) 
  
  // configure UE-spec DCI for UL Grant
838 839
  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);
840 841 842 843 844 845 846 847
    smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i);
  }
  
#endif
  
  
  // get the hard_pid for this subframe 
  harq_pid = subframe2harq_pid(fp,
848
			       pdcch_alloc2ul_frame(fp,frame,subframe),
849 850 851
			       pdcch_alloc2ul_subframe(fp,subframe));
  
  if (harq_pid==255) { // should not happen, log an error and exit, this is a fatal error
852
    LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,frame);
853 854 855 856
    mac_xface->macphy_exit("FATAL\n"); 
  }
  
  if ((dci_alloc->rnti  >= CBA_RNTI) && (dci_alloc->rnti < P_RNTI))
857
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1;
858
  else
859
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
860 861
  
}
862

863
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,int abstraction_flag) {
864

865 866
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
867 868 869
  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;
870
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
871 872 873 874 875 876 877 878
  uint8_t *DLSCH_pdu=NULL;
  uint8_t DLSCH_pdu_tmp[768*8];
  uint8_t DLSCH_pdu_rar[256];
  int i;

  LOG_D(PHY,
	"[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 %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n",
	eNB->Mod_id, dlsch->rnti,harq_pid,
879
	frame, subframe, input_buffer_length,
880 881 882 883 884
	get_G(fp,
	      dlsch_harq->nb_rb,
	      dlsch_harq->rb_alloc,
	      get_Qm(dlsch_harq->mcs),
	      dlsch_harq->Nl,
885
	      num_pdcch_symbols,frame,subframe),
886 887 888 889 890
	dlsch_harq->nb_rb,
	dlsch_harq->mcs,
	pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	dlsch_harq->rvidx,
	dlsch_harq->round);
891

892
#if defined(MESSAGE_CHART_GENERATOR_PHY)
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
  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,
			   num_pdcch_symbols,frame,subframe),
		     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]++;
918

919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
    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);
      }
      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;
942
	    
943 944 945 946 947 948 949 950 951 952
	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;
953
	      
954 955 956 957 958
	  generate_eNB_ulsch_params_from_rar(DLSCH_pdu,
					     frame,
					     (subframe),
					     eNB->ulsch[(uint32_t)UE_id],
					     fp);
959
	      
960
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 1;
961
	      
962 963 964 965 966 967 968 969 970 971 972
	  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);
973
	}
974 975 976 977 978
	if (ue_stats) ue_stats->total_TBS_MAC += dlsch_harq->TBS;
      }
    }
    else {
      DLSCH_pdu = DLSCH_pdu_tmp;
979
	  
980 981 982
      for (i=0; i<input_buffer_length; i++)
	DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
    }
983 984
	
#if defined(SMBV) 
985

986 987 988 989 990
    // 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);
    }
991

992
#endif
993

994

995

996 997
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
998
    LOG_T(PHY,"eNB DLSCH SDU: \n");
999

1000 1001 1002
    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_pdu->dci_alloc[i].rnti), T_INT(DCI_pdu->dci_alloc[i].format),
      T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid));
1003

1004
    eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE;
1005

1006 1007
    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);
1008 1009


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

1013
    LOG_T(PHY,"\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
1014
#endif
1015
#endif
1016 1017
  } else {
    ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++;
1018 1019
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1020
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
1021 1022
#endif
#endif
1023
  }
1024

1025
  if (abstraction_flag==0) {
1026

1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
    LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag);
    // 36-212
    start_meas(&eNB->dlsch_encoding_stats);
    dlsch_encoding(DLSCH_pdu,
		   fp,
		   num_pdcch_symbols,
		   dlsch,
		   frame,subframe,
		   &eNB->dlsch_rate_matching_stats,
		   &eNB->dlsch_turbo_encoding_stats,
		   &eNB->dlsch_interleaving_stats);
    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,
			   num_pdcch_symbols,frame,subframe),
		     0,
		     subframe<<1);
    stop_meas(&eNB->dlsch_scrambling_stats);
    start_meas(&eNB->dlsch_modulation_stats);


    dlsch_modulation(eNB->common_vars.txdataF[0],
		     AMP,
		     subframe,
		     fp,
		     num_pdcch_symbols,
		     dlsch,
		     dlsch1);
1063
	
1064 1065
    stop_meas(&eNB->dlsch_modulation_stats);
  }
1066 1067


1068
#ifdef PHY_ABSTRACTION
1069 1070 1071 1072 1073 1074 1075
  else {
    start_meas(&eNB->dlsch_encoding_stats);
    dlsch_encoding_emul(eNB,
			DLSCH_pdu,
			dlsch);
    stop_meas(&eNB->dlsch_encoding_stats);
  }
1076

1077
#endif
1078
  dlsch->active = 0;
1079
}
1080

1081
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
1082
			   eNB_rxtx_proc_t *proc,
1083 1084 1085 1086 1087
			   uint8_t abstraction_flag,
                           relaying_type_t r_type,
			   PHY_VARS_RN *rn)
{
  UNUSED(rn);
1088 1089
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
1090
  //  uint16_t input_buffer_length;
1091 1092 1093 1094
  uint32_t i,aa;
  uint8_t harq_pid;
  DCI_PDU *DCI_pdu;
  DCI_PDU DCI_pdu_tmp;
1095
  int8_t UE_id=0;
1096 1097 1098
  uint8_t num_pdcch_symbols=0;
  uint8_t ul_subframe;
  uint32_t ul_frame;
1099
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1100
  DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL;
1101

1102 1103 1104 1105 1106
#if defined(SMBV) 
  // counts number of allocations in subframe
  // there is at least one allocation for PDCCH
  uint8_t smbv_alloc_cnt = 1;
#endif
1107

1108
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),1);
1109
  start_meas(&eNB->phy_proc_tx);
1110

1111 1112
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    // If we've dropped the UE, go back to PRACH mode for this UE
1113 1114 1115 1116 1117
    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);
      }
    }
1118
    if (eNB->UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) {
1119
      LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n",
1120 1121
            eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->UE_stats[i].ulsch_consecutive_errors);
      eNB->UE_stats[i].ulsch_consecutive_errors=0;
1122 1123 1124
      mac_xface->UL_failure_indication(eNB->Mod_id,
				       eNB->CC_id,
				       frame,
1125
				       eNB->UE_stats[i].crnti,
1126 1127
				       subframe);
				       
Raymond Knopp's avatar
 
Raymond Knopp committed
1128
    }
1129
	
1130

1131
  }
1132 1133 1134


  // Get scheduling info for next subframe
1135
  // This is called only for the CC_id = 0 and triggers scheduling for all CC_id's
1136 1137
  if (eNB->mac_enabled==1) {
    if (eNB->CC_id == 0) {
1138
      mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,frame,subframe);//,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1139
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1140
  }
1141

1142
  // clear the transmit data array for the current subframe
1143 1144
  if (abstraction_flag==0) {
    for (aa=0; aa<fp->nb_antennas_tx_eNB; aa++) {      
1145
      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
1146 1147 1148
             0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
    }
  }
1149

1150
  if (is_pmch_subframe(frame,subframe,fp)) {
1151
    pmch_procedures(eNB,proc,rn,abstraction_flag,r_type);
1152 1153 1154
  }
  else {
    // this is not a pmch subframe, so generate PSS/SSS/PBCH
1155
    common_signal_procedures(eNB,proc,abstraction_flag);
1156
  }
1157

1158
#if defined(SMBV) 
1159

Raymond Knopp's avatar
 
Raymond Knopp committed
1160
  // PBCH takes one allocation
1161
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
1162
    if (subframe==0)
Raymond Knopp's avatar
 
Raymond Knopp committed
1163 1164
      smbv_alloc_cnt++;
  }
1165

1166
#endif
1167

1168
  if (eNB->mac_enabled==1) {
1169 1170
    // Parse DCI received from MAC
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
1171 1172
    DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
				     eNB->CC_id,
1173
				     frame,
1174 1175 1176 1177
				     subframe);
  }
  else {
    DCI_pdu = &DCI_pdu_tmp;
1178
#ifdef EMOS_CHANNEL
1179
    fill_dci_emos(DCI_pdu,eNB);
1180
#else
1181
    fill_dci(DCI_pdu,eNB,proc);
1182
#endif
1183
  }
1184

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

1189 1190 1191
  if ((subframe_select(fp,ul_subframe)==SF_UL) ||
      (fp->frame_type == FDD)) {
    harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
1192

1193
    // clear DCI allocation maps for new subframe
1194
    for (i=0; i<NUMBER_OF_UE_MAX; i++)
1195 1196 1197
      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
1198 1199
      }
  }
1200

Raymond Knopp's avatar
 
Raymond Knopp committed
1201
  // clear previous allocation information for all UEs
1202
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
1203 1204
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1205
  }
1206 1207


1208
  num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
Raymond Knopp's avatar
Raymond Knopp committed
1209
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
1210 1211
        DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);

1212
#if defined(SMBV) 
Raymond Knopp's avatar
 
Raymond Knopp committed
1213
  // Sets up PDCCH and DCI table
1214 1215
  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);
1216
    dump_dci(fp,&DCI_pdu->dci_alloc[0]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1217 1218
    smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
  }
1219 1220
#endif

1221 1222
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);

1223
  // loop over all DCIs for this subframe to generate DLSCH allocations
1224 1225 1226 1227 1228
  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);
1229
    dci_alloc = &DCI_pdu->dci_alloc[i];
1230

1231 1232 1233 1234
    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);
1235 1236
      else
	UE_id = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1237
    }
1238 1239
    else UE_id=0;
    
1240
    generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
1241

Raymond Knopp's avatar
 
Raymond Knopp committed
1242
  }
1243

1244 1245
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

Raymond Knopp's avatar
 
Raymond Knopp committed
1246
  // Apply physicalConfigDedicated if needed
1247 1248 1249 1250
  // 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
1251
  for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
1252 1253 1254
    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);
1255 1256
      else
	UE_id = i;
1257
      
1258
      if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
1259
	LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
1260
	mac_xface->macphy_exit("FATAL\n"); 
1261
      }
1262
      generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1263
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1264
  }
1265

1266 1267


Lionel Gauthier's avatar
Lionel Gauthier committed
1268 1269


Raymond Knopp's avatar
 
Raymond Knopp committed
1270 1271
  // 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
1272

1273 1274

  } else { // for emulation!!
1275 1276
    eNB->num_ue_spec_dci[(subframe)&1]=0;
    eNB->num_common_dci[(subframe)&1]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1277
  }
1278

Raymond Knopp's avatar
 
Raymond Knopp committed
1279
  if (abstraction_flag == 0) {
1280

1281
    if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) {
1282
      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,
1283
            DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
1284 1285
    }

1286 1287 1288 1289 1290 1291

    num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_ue_spec_dci,
                                         DCI_pdu->Num_common_dci,
                                         DCI_pdu->dci_alloc,
                                         0,
                                         AMP,
1292
                                         fp,
1293
                                         eNB->common_vars.txdataF[0],
1294
                                         subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1295

Raymond Knopp's avatar
 
Raymond Knopp committed
1296
  }
1297

1298
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
Raymond Knopp's avatar
 
Raymond Knopp committed
1299
  else {
1300
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
1301
    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
1302
  }
1303

1304 1305
#endif

1306
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
1307

Raymond Knopp's avatar
 
Raymond Knopp committed
1308
  // Check for SI activity
1309

1310
  if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
1311

1312
    pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols,abstraction_flag);
1313

1314
#if defined(SMBV) 
1315

Raymond Knopp's avatar
 
Raymond Knopp committed
1316
    // Configures the data source of allocation (allocation is configured by DCI)
1317 1318
    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
1319 1320
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
    }
1321

1322
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1323
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1324

Raymond Knopp's avatar
 
Raymond Knopp committed
1325
  // Check for RA activity
1326
  if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
1327

1328
#if defined(SMBV) 
1329

1330
    // Configures the data source of allocation (allocation is configured by DCI)
1331 1332
    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);
1333 1334 1335
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length);
    }
    
1336
#endif
1337 1338
    
    
1339
    LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA),Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n",
1340
	  eNB->Mod_id,
1341
	  frame, subframe,
1342 1343
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
1344
    
1345
    pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols,abstraction_flag);
1346 1347
    
    
1348
    eNB->dlsch_ra->active = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1349
  }
1350
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1351
  // Now scan UE specific DLSCH
1352
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
1353 1354 1355 1356
    {
      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)) {
1357

1358
	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,abstraction_flag);
1359 1360


Raymond Knopp's avatar
 
Raymond Knopp committed
1361
      }
Lionel Gauthier's avatar
Lionel Gauthier committed
1362

1363 1364 1365
      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)) {
1366

1367 1368
	// 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
1369
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1370
    }
1371

1372 1373


Raymond Knopp's avatar
 
Raymond Knopp committed
1374
  // if we have PHICH to generate
1375

1376
  if (is_phich_subframe(fp,subframe))
1377 1378 1379 1380 1381 1382 1383
    {
      generate_phich_top(eNB,
			 proc,
			 AMP,
			 0,
			 abstraction_flag);
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1384

1385 1386


1387
#ifdef EMOS
1388
  phy_procedures_emos_eNB_TX(subframe, eNB);
1389
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1390

1391
#if !(defined(EXMIMO) || defined(OAI_USRP) || defined (CPRIGW))
1392
  
1393
  if (abstraction_flag==0)
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
    {
      start_meas(&eNB->ofdm_mod_stats);
      do_OFDM_mod(eNB->common_vars.txdataF[0],
		  eNB->common_vars.txdata[0],
		  frame,subframe<<1,
		  fp);
      do_OFDM_mod(eNB->common_vars.txdataF[0],
		  eNB->common_vars.txdata[0],
		  frame,1+(subframe<<1),
		  fp);
      stop_meas(&eNB->ofdm_mod_stats);
    }
1406

Raymond Knopp's avatar
 
Raymond Knopp committed
1407
#endif
1408

1409
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),0);
1410
  stop_meas(&eNB->phy_proc_tx);
1411
  
1412 1413
}

1414
void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid)
1415
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1416
  // this prepares the demodulation of the first PUSCH of a new user, containing Msg3
1417 1418
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1419

Raymond Knopp's avatar
 
Raymond Knopp committed
1420
  LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
1421
        eNB->Mod_id,
1422
        frame,subframe,
1423 1424 1425 1426
        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;
1427

1428 1429 1430
  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))   {
1431

1432
    //    harq_pid = 0;
1433

1434 1435 1436
    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
1437
    LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
1438
          eNB->Mod_id,
1439
          frame,subframe,UE_id);
1440 1441 1442 1443 1444 1445 1446 1447 1448
  }
}


// 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

1449
void process_HARQ_feedback(uint8_t UE_id,
1450
                           PHY_VARS_eNB *eNB,
1451
			   eNB_rxtx_proc_t *proc,
1452 1453 1454 1455 1456
                           uint8_t pusch_flag,
                           uint8_t *pucch_payload,
                           uint8_t pucch_sel,
                           uint8_t SR_payload)
{
1457

1458
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1459
  uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe;
1460 1461
  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];
1462
  LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
1463
  uint8_t subframe_m4,M,m;
1464 1465
  int mp;
  int all_ACKed=1,nb_alloc=0,nb_ACK=0;
1466 1467
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1468
  int harq_pid = subframe2harq_pid( fp,frame,subframe);
1469

1470 1471

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

1474 1475
    dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
    M=1;
1476

1477
    if (pusch_flag == 1) {
1478
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1479
      if (dlsch->subframe_tx[subframe_m4]==1)
1480 1481
	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);
1482 1483
    }
    else {
1484
      dlsch_ACK[0] = pucch_payload[0];
1485
      LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",eNB->Mod_id,
1486
	    frame,dlsch_ACK[0],subframe_m4);
kaltenbe's avatar
kaltenbe committed
1487
      /*
1488
	if (dlsch_ACK[0]==0)
1489
	AssertFatal(0,"Exiting on NAK on PUCCH\n");
kaltenbe's avatar
kaltenbe committed
1490
      */
1491
    }
1492

Lionel Gauthier's avatar
Lionel Gauthier committed
1493 1494 1495

#if defined(MESSAGE_CHART_GENERATOR_PHY)
    MSC_LOG_RX_MESSAGE(
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505
		       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
1506
#endif
1507 1508
  } else { // TDD Handle M=1,2 cases only

1509
    M=ul_ACK_subframe2_M(fp,
1510 1511
                         subframe);

1512 1513 1514 1515 1516 1517 1518 1519
    // 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

1520
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1521
      dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling)
1522
	?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];
1523
    }
1524

1525
    else {  // PUCCH ACK/NAK
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
      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;
        }
1561
      }
1562
    }
1563 1564 1565 1566
  }

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

    for (m=0; m<M; m++) {
1570
      dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1571 1572
						 subframe,
						 m);
1573 1574 1575

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

1578 1579
    if (nb_alloc == nb_ACK)
      all_ACKed = 1;
1580
    else
1581
      all_ACKed = 0;
1582 1583 1584
  }


1585
  for (m=0,mp=-1; m<M; m++) {
1586

1587
    dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1588 1589
					       subframe,
					       m);
1590

1591 1592
    if (dlsch->subframe_tx[dl_subframe]==1) {
      if (pusch_flag == 1)
1593
        mp++;
1594
      else
1595
        mp = m;
1596

1597
      dl_harq_pid[m]     = dlsch->harq_ids[dl_subframe];
1598

1599
      if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
1600 1601 1602 1603
        if ((SR_payload == 1)&&(all_ACKed == 1))
          dlsch_ACK[m] = 1;
        else
          dlsch_ACK[m] = 0;
1604
      }
1605

1606
      if (dl_harq_pid[m]<dlsch->Mdlharq) {
1607 1608
        dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
1609
        LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id,
1610 1611 1612 1613 1614 1615 1616 1617 1618
              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");

1619
#endif
1620 1621 1622 1623 1624 1625 1626 1627

        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
1628
            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,
1629
                  dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
1630
#endif
1631

1632
            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),
1633
              T_INT(dl_harq_pid[m]));
1634

1635 1636 1637 1638 1639 1640 1641 1642 1643
            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++;

1644

1645
            if (dlsch_harq_proc->round == dlsch->Mlimit) {
1646 1647
              // This was the last round for DLSCH so reset round and increment l2_error counter
#ifdef DEBUG_PHY_PROC
1648
              LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",eNB->Mod_id,
1649
                    dlsch->rnti,dl_harq_pid[m]);
1650
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1651
#if defined(MESSAGE_CHART_GENERATOR_PHY)
1652
              MSC_LOG_EVENT(MSC_PHY_ENB, "0 HARQ DLSCH Failed RNTI %"PRIx16" round %u",
1653 1654
                            dlsch->rnti,
                            dlsch_harq_proc->round);
Lionel Gauthier's avatar
Lionel Gauthier committed
1655
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1656

1657 1658 1659 1660 1661 1662 1663
              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
1664
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
1665
                  dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
1666
#endif
1667

1668
            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),
1669
              T_INT(dl_harq_pid[m]));
1670

1671 1672 1673 1674 1675 1676 1677 1678
            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 +
1679
	      eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1680 1681
            /*
              ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
1682
              eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696
            */
          }

          // 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);
1697
#endif
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719

          // 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;
          }


        }
1720
      }
1721
    }
1722 1723 1724
  }
}

1725
void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
1726
		      eNB_rxtx_proc_t *proc,
1727 1728 1729 1730 1731 1732
                      uint8_t UE_id,
                      int16_t *n1_pucch0,
                      int16_t *n1_pucch1,
                      int16_t *n1_pucch2,
                      int16_t *n1_pucch3)
{
1733

1734
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
1735
  uint8_t nCCE0,nCCE1;
1736
  int sf;
1737 1738
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1739 1740

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

1743 1744
    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];
1745
      *n1_pucch1 = -1;
1746
    } else {
1747 1748 1749
      *n1_pucch0 = -1;
      *n1_pucch1 = -1;
    }
1750
  } else {
1751

1752 1753 1754
    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
1755
        /*  if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
1756 1757 1758 1759 1760
	    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;*/
1761

1762 1763
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1764 1765 1766 1767 1768 1769 1770
          *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

1771 1772
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1773 1774 1775 1776 1777 1778 1779 1780 1781
          *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;
1782 1783
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1784 1785 1786 1787 1788 1789 1790
          *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;
1791 1792
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4];
1793 1794 1795 1796 1797 1798 1799
          *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",
1800
              eNB->Mod_id,
1801 1802 1803
              frame,
              subframe,frame_parms->tdd_config);
        return;
1804
      }
1805

1806
      break;
1807

1808 1809
    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)
1810 1811
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
1812 1813 1814 1815
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1816 1817
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1818 1819 1820 1821 1822
          *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",
1823
              eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7],eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]);
1824

1825 1826
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[8];
1827 1828 1829 1830 1831
          *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;

1832 1833
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7];
1834 1835 1836 1837 1838
          *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
1839 1840
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1841 1842 1843 1844
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1845 1846
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1847 1848 1849 1850 1851
          *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",
1852
              eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
1853
        return;
1854
      }
1855

1856
      break;
1857 1858
    }  // switch tdd_config

1859 1860 1861
    // Don't handle the case M>2
    *n1_pucch2 = -1;
    *n1_pucch3 = -1;
1862 1863 1864
  }
}

1865
void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag)
1866
{
1867

1868
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1869 1870 1871 1872
  uint16_t preamble_energy_list[64],preamble_delay_list[64];
  uint16_t preamble_max,preamble_energy_max;
  uint16_t i;
  int8_t UE_id;
1873 1874
  int subframe = eNB->proc.subframe_prach;
  int frame = eNB->proc.frame_prach;
1875
  uint8_t CC_id = eNB->CC_id;
1876

1877 1878
  memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
  memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
1879

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

1884

1885
    rx_prach(eNB,
1886 1887 1888 1889 1890 1891 1892
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
  } else {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {

1893
      LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
1894
            UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
1895
            PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
1896
            fp->prach_config_common.rootSequenceIndex,
1897 1898
            PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex);

Raymond Knopp's avatar
 
Raymond Knopp committed
1899
      if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) &&
1900
          (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex ==
1901
           fp->prach_config_common.rootSequenceIndex) ) {
1902 1903 1904
        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;

1905
      }
1906
    }
1907
  }
1908

1909 1910 1911
  preamble_energy_max = preamble_energy_list[0];
  preamble_max = 0;

1912
  for (i=1; i<64; i++) {
1913 1914 1915 1916
    if (preamble_energy_max < preamble_energy_list[i]) {
      preamble_energy_max = preamble_energy_list[i];
      preamble_max = i;
    }
1917 1918 1919
  }

#ifdef DEBUG_PHY_PROC
1920
  LOG_D(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
1921 1922 1923
        preamble_max,
        preamble_energy_list[preamble_max],
        preamble_delay_list[preamble_max]);
1924 1925
#endif

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

1928
    UE_id = find_next_ue_index(eNB);
1929
 
1930
    if (UE_id>=0) {
1931
      eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
1932

1933
      eNB->UE_stats[(uint32_t)UE_id].sector = 0;
1934
      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",
1935 1936
            eNB->Mod_id,
            eNB->CC_id,
1937 1938
            frame,
            subframe,
1939
	    UE_id,
1940 1941 1942 1943
            preamble_max,
            preamble_energy_max/10,
            preamble_energy_max%10,
            preamble_delay_list[preamble_max]);
1944

1945
      if (eNB->mac_enabled==1) {
1946 1947
        uint8_t update_TA=4;

1948
        switch (fp->N_RB_DL) {
1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965
        case 6:
          update_TA = 16;
          break;

        case 25:
          update_TA = 4;
          break;

        case 50:
          update_TA = 2;
          break;

        case 100:
          update_TA = 1;
          break;
        }

1966 1967 1968 1969 1970 1971
	mac_xface->initiate_ra_proc(eNB->Mod_id,
				    eNB->CC_id,
				    frame,
				    preamble_max,
				    preamble_delay_list[preamble_max]*update_TA,
				    0,subframe,0);
1972 1973
      }      

1974
    } else {
1975
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many");
1976
      LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
1977
            eNB->Mod_id,frame, subframe);
1978
    }
1979 1980 1981
  }
}

1982
void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1983

1984
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1985
  uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0};
1986 1987 1988
  int16_t n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3;
  uint8_t do_SR = 0;
  uint8_t pucch_sel = 0;
1989
  int32_t metric0=0,metric1=0,metric0_SR=0;
1990 1991
  ANFBmode_t bundling_flag;
  PUCCH_FMT_t format;
1992 1993
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
1994

1995 1996 1997
  if ((eNB->dlsch[UE_id][0]) &&
      (eNB->dlsch[UE_id][0]->rnti>0) &&
      (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { 
1998

1999
    // check SR availability
2000 2001 2002
    do_SR = is_SR_subframe(eNB,proc,UE_id);
    //      do_SR = 0;
    
2003 2004
    // Now ACK/NAK
    // First check subframe_tx flag for earlier subframes
2005

2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052
    get_n1_pucch_eNB(eNB,
		     proc,
		     UE_id,
		     &n1_pucch0,
		     &n1_pucch1,
		     &n1_pucch2,
		     &n1_pucch3);
    
    LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d, subframe %d Checking for PUCCH (%d,%d,%d,%d) SR %d\n",
	  eNB->Mod_id,eNB->dlsch[UE_id][0]->rnti,
	  frame,subframe,
	  n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR);
    
    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
      
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
	eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
	break;
      case 15:
	eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
	break;
      case 25:
	eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
	break;
      case 50:
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
	break;
      case 75:
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
	break;
      case 100:
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
	break;
      default:
	LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
	break;
      }
      
      if (do_SR == 1) {
	eNB->UE_stats[UE_id].sr_total++;
2053 2054


2055 2056 2057 2058 2059 2060 2061 2062
	if (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,
2063
				frame,
2064 2065 2066
				subframe,
				PUCCH1_THRES);
	
2067
#ifdef PHY_ABSTRACTION
2068 2069
	else {
	  metric0_SR = rx_pucch_emul(eNB,
2070
				     proc,
2071 2072 2073 2074 2075 2076 2077 2078
				     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);
	}
	
2079
#endif
2080

2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099
	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);
2100
	  }
2101 2102 2103 2104
	}
      }// do_SR==1
      
      if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR
2105
      } else if (eNB->frame_parms.frame_type==FDD) { // FDD
2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121
	// 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 (abstraction_flag == 0) {
	  
	  
	  
	  metric0 = rx_pucch(eNB,
			     pucch_format1a,
			     UE_id,
			     (uint16_t)n1_pucch0,
			     0, //n2_pucch
			     0, // shortened format
			     pucch_payload0,
2122
			     frame,
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133
			     subframe,
			     PUCCH1a_THRES);
	  
	  if (metric0 < metric0_SR)
	    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,
2134
			     frame,
2135 2136
			     subframe,
			     PUCCH1a_THRES);
2137
	  
2138
	}
2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183
	
	if (eNB->mac_enabled==1) {
	  mac_xface->SR_indication(eNB->Mod_id,
				   eNB->CC_id,
				   frame,
				   eNB->dlsch[UE_id][0]->rnti,subframe);
	}
      }
    }// do_SR==1
    
    if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR
    } 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 (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);
	  
	if (metric0 < metric0_SR)
	  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);
      }
      else {
2184
#ifdef PHY_ABSTRACTION
2185 2186 2187 2188 2189 2190
	metric0 = rx_pucch_emul(eNB,
				proc,
				UE_id,
				pucch_format1a,
				0,
				pucch_payload0);
2191
#endif
2192
      }
2193
	
2194
#ifdef DEBUG_PHY_PROC
2195 2196 2197 2198 2199
      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);
2200
#endif
2201
	
2202 2203 2204 2205 2206
      process_HARQ_feedback(UE_id,eNB,proc,
			    0,// pusch_flag
			    pucch_payload0,
			    2,
			    SR_payload);
2207

2208 2209
    } // FDD
    else {  //TDD
2210

2211
      bundling_flag = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode;
2212

2213
      // fix later for 2 TB case and format1b
Raymond Knopp's avatar
Raymond Knopp committed
2214

2215 2216 2217 2218 2219 2220 2221
      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;
      }
2222

2223 2224
      // if SR was detected, use the n1_pucch from SR
      if (SR_payload==1) {
2225
#ifdef DEBUG_PHY_PROC
2226 2227 2228 2229
	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);
2230
#endif
2231

2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243
	if (abstraction_flag == 0)
	  metric0_SR = 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 {
2244
#ifdef PHY_ABSTRACTION
2245 2246 2247 2248 2249
	  metric0 = rx_pucch_emul(eNB,proc,
				  UE_id,
				  format,
				  0,
				  pucch_payload0);
2250
#endif
2251 2252
	}
      } else { //using n1_pucch0/n1_pucch1 resources
2253
#ifdef DEBUG_PHY_PROC
2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275
	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);
#endif
	metric0=0;
	metric1=0;

	// Check n1_pucch0 metric
	if (n1_pucch0 != -1) {
	  if (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 {
2276
#ifdef PHY_ABSTRACTION
2277 2278 2279 2280 2281 2282
	    metric0 = rx_pucch_emul(eNB,
				    proc,
				    UE_id,
				    format,
				    0,
				    pucch_payload0);
2283
#endif
2284 2285
	  }
	}
2286

2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300
	// Check n1_pucch1 metric
	if (n1_pucch1 != -1) {
	  if (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 {
2301
#ifdef PHY_ABSTRACTION
2302 2303 2304 2305 2306 2307
	    metric1 = rx_pucch_emul(eNB,
				    proc,
				    UE_id,
				    format,
				    1,
				    pucch_payload1);
2308
#endif
2309 2310 2311
	  }
	}
      }
2312

2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327
      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
2328
      }
2329

2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340
#ifdef DEBUG_PHY_PROC
      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]);
#endif
      process_HARQ_feedback(UE_id,eNB,proc,
			    0,// pusch_flag
			    pucch_payload,
			    pucch_sel,
			    SR_payload);
2341
    }
2342
  }  
2343
}
2344

2345

2346
void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) {
2347

2348 2349
  uint8_t access_mode;
  int num_active_cba_groups;
2350 2351
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2352 2353
  uint16_t rnti=0;
  int ret=0;
2354
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2355

2356
  num_active_cba_groups = eNB->ulsch[UE_id]->num_active_cba_groups;
2357
  
2358
  if ((eNB->ulsch[UE_id]) &&
2359
      (num_active_cba_groups > 0) &&
2360 2361
      (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)) {
2362 2363 2364 2365
    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",
2366
	  eNB->Mod_id,harq_pid,
2367
	  frame,subframe,
2368
	  UE_id, (uint16_t)eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->UE_stats[UE_id].mode]);
2369 2370 2371
#endif
    
    if (abstraction_flag==0) {
2372
      rx_ulsch(eNB,proc,
2373
	       eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2374
	       UE_id,
2375
	       eNB->ulsch,
2376 2377 2378 2379 2380
	       0);
    }
    
#ifdef PHY_ABSTRACTION
    else {
2381
      rx_ulsch_emul(eNB,proc,
2382
		    eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2383
		    UE_id);
2384 2385 2386 2387 2388
    }
    
#endif
    
    if (abstraction_flag == 0) {
2389
      ret = ulsch_decoding(eNB,proc,
2390 2391
			   UE_id,
			   0, // control_only_flag
2392 2393
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->V_UL_DAI,
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2394 2395 2396 2397
    }
    
#ifdef PHY_ABSTRACTION
    else {
2398
      ret = ulsch_decoding_emul(eNB,
2399
				proc,
2400 2401 2402 2403 2404 2405
				UE_id,
				&rnti);
    }
    
#endif
    
2406
    if (eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2407 2408
#ifdef DEBUG_PHY_PROC
      
2409
      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);
2410 2411
#endif
      access_mode = UNKNOWN_ACCESS;
2412 2413 2414
      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],
2415
		  fp->N_RB_DL,
2416
		  &rnti, &access_mode);
2417
      eNB->UE_stats[UE_id].rank = eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_RI[0];
2418 2419
    }
    
2420 2421
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0;
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE;
2422
      
2423 2424 2425 2426
    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)) {
2427
#ifdef DEBUG_PHY_PROC
2428 2429 2430
      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);
2431
#endif
2432 2433 2434 2435
      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;
    }
2436

2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451
    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;
2452 2453
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500
      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
	if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) {
	  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
2501
  }
2502

2503
}
2504

2505

2506
void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) {
2507

2508
  int l;
2509
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2510

2511
  eNB_proc_t *proc = &eNB->proc;
2512 2513 2514

  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2515

Sandeep Kumar's avatar
Sandeep Kumar committed
2516 2517
  uint8_t seqno=0;

2518
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 1 );
2519
  
2520
  start_meas(&eNB->phy_proc_rx);
2521

2522
#ifdef DEBUG_PHY_PROC
2523
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe);
2524 2525
#endif

2526
  if (abstraction_flag==0) {
2527 2528

    if ((eNB->node_function == NGFI_RRU_IF4) || 
2529 2530
        (eNB->node_function == eNodeB_3GPP)  ||
        (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing
2531

2532 2533
      // now do common RX processing for first slot in subframe
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
Raymond Knopp's avatar
Raymond Knopp committed
2534 2535
      remove_7_5_kHz(eNB,proc->subframe_rx<<1);
      remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1));
2536 2537 2538 2539
      for (l=0; l<fp->symbols_per_tti/2; l++) {
        slot_fep_ul(fp,
                    &eNB->common_vars,
                    l,
Raymond Knopp's avatar
Raymond Knopp committed
2540
                    proc->subframe_rx<<1,
2541 2542 2543 2544 2545 2546
                    0,
                    0
                    );
        slot_fep_ul(fp,
                    &eNB->common_vars,
                    l,
Raymond Knopp's avatar
Raymond Knopp committed
2547
                    1+(proc->subframe_rx<<1),
2548 2549 2550 2551
                    0,
                    0
                    );
      }
Raymond Knopp's avatar
Raymond Knopp committed
2552

2553 2554 2555
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);

      if (eNB->node_function == NGFI_RRU_IF4) {
2556
        /// **** send_IF4 of rxdataF to RCC (no prach now) **** ///
2557
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 );   
2558
        send_IF4(eNB, proc->frame_rx, proc->subframe_rx, IF4_PULFFT, 0);
2559
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 );   
2560
      }    
2561 2562
    }
    else if (eNB->node_function == NGFI_RRU_IF5) {
2563 2564 2565
      /// **** 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);
2566 2567 2568 2569 2570 2571
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );          
    }
    
    /// **** send_IF4 of prach to RCC **** /// done in prach thread (below)
    // check if we have to detect PRACH first
    if ((eNB->node_function != NGFI_RRU_IF5) && 
2572
        (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0)) { // any other node must call prach procedure
2573 2574
      // wake up thread for PRACH RX
      if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
2575 2576 2577
        LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach );
        exit_fun( "error locking mutex_prach" );
        return;
2578 2579 2580 2581 2582 2583 2584 2585 2586 2587
      }
      
      int cnt_prach = ++proc->instance_cnt_prach;
      // set timing for prach thread
      proc->frame_prach = proc->frame_rx;
      proc->subframe_prach = proc->subframe_rx;
      
      pthread_mutex_unlock( &proc->mutex_prach );
      
      if (cnt_prach == 0) {
2588 2589 2590 2591 2592 2593
        // the thread was presumably waiting where it should and 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;
        }
2594
      } else {
2595 2596 2597
        LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach);
        exit_fun( "PRACH thread busy" );
        return;
2598
      }
2599
    }
2600
    
2601
  } else { // grab transport channel information from network interface
2602 2603

  }
2604

2605
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 0 );
2606 2607
}

2608

2609
void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const uint8_t abstraction_flag,const relaying_type_t r_type)
2610
{
2611
  //RX processing for ue-specific resources (i
2612
  UNUSED(r_type);
2613
  uint32_t ret=0,i,j,k;
2614 2615 2616 2617 2618
  uint32_t harq_pid, harq_idx, round;
  uint8_t nPRS;
  int sync_pos;
  uint16_t rnti=0;
  uint8_t access_mode;
2619
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2620

2621 2622
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2623

2624
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 1 );
2625
  start_meas(&eNB->phy_proc_rx);
2626
#ifdef DEBUG_PHY_PROC
2627
  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
2628
#endif
2629

2630
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
2631

2632 2633 2634
  T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
    T_BUFFER(&eNB->lte_eNB_common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
             eNB->frame_parms.samples_per_tti * 4));
2635

2636 2637 2638 2639
  eNB->rb_mask_ul[0]=0;
  eNB->rb_mask_ul[1]=0;
  eNB->rb_mask_ul[2]=0;
  eNB->rb_mask_ul[3]=0;
2640 2641 2642



2643
  // Check for active processes in current subframe
2644
  harq_pid = subframe2harq_pid(fp,
2645 2646 2647 2648
                               frame,subframe);

  // reset the cba flag used for collision detection
  for (i=0; i < NUM_MAX_CBA_GROUP; i++) {
2649
    eNB->cba_last_reception[i]=0;
2650 2651 2652 2653 2654
  }

  // Do PUCCH processing first

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2655
    pucch_procedures(eNB,proc,i,harq_pid,abstraction_flag);
2656
  }
2657

2658
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2659

2660
    // check for Msg3
2661
    if (eNB->mac_enabled==1) {
2662
      if (eNB->UE_stats[i].mode == RA_RESPONSE) {
2663
	process_Msg3(eNB,proc,i,harq_pid);
2664 2665
      }
    }
2666 2667


2668 2669 2670
    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;
2671

2672 2673 2674
    if ((eNB->ulsch[i]) &&
        (eNB->ulsch[i]->rnti>0) &&
        (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) {
2675
      // UE is has ULSCH scheduling
2676
      round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
2677
 
2678
      for (int rb=0;
2679
           rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
2680
	   rb++) {
2681
	int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
2682
	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
2683
      }
2684

2685

2686
      if (eNB->ulsch[i]->Msg3_flag == 1) {
2687
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
2688
              eNB->Mod_id,
2689 2690
              frame,
              subframe,
2691
              eNB->UE_stats[i].sector);
2692 2693
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1);
      } else {
2694

2695
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n",
2696
              eNB->Mod_id,
2697 2698 2699
              frame,
              subframe,
              i,
2700
              mode_string[eNB->UE_stats[i].mode]);
2701
      }
2702 2703


2704
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
2705

2706
      eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
2707
				    nPRS)%12;
2708

2709
      if (fp->frame_type == FDD ) {
2710
        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
2711

2712 2713
        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
2714
        } else {
2715
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
2716
        }
2717
      }
2718

2719 2720
      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",
2721
            eNB->Mod_id,harq_pid,frame,subframe,
2722 2723 2724 2725 2726 2727 2728 2729 2730 2731
            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,
2732
            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
2733
            nPRS,
2734 2735 2736 2737
            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;
2738
      start_meas(&eNB->ulsch_demodulation_stats);
2739

2740
      if (abstraction_flag==0) {
2741
        rx_ulsch(eNB,proc,
2742
                 eNB->UE_stats[i].sector,  // this is the effective sector id
2743
                 i,
2744
                 eNB->ulsch,
2745 2746
                 0);
      }
2747

2748 2749
#ifdef PHY_ABSTRACTION
      else {
2750
        rx_ulsch_emul(eNB,proc,
2751
                      eNB->UE_stats[i].sector,  // this is the effective sector id
2752 2753
                      i);
      }
2754

2755
#endif
2756
      stop_meas(&eNB->ulsch_demodulation_stats);
2757

2758

2759
      start_meas(&eNB->ulsch_decoding_stats);
2760

2761
      if (abstraction_flag == 0) {
2762
        ret = ulsch_decoding(eNB,proc,
2763 2764
                             i,
                             0, // control_only_flag
2765 2766
                             eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
			     eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2767
      }
2768

2769 2770
#ifdef PHY_ABSTRACTION
      else {
2771 2772
        ret = ulsch_decoding_emul(eNB,
				  proc,
2773 2774 2775
                                  i,
                                  &rnti);
      }
2776

2777
#endif
2778
      stop_meas(&eNB->ulsch_decoding_stats);
2779

2780
      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",
2781
            eNB->Mod_id,harq_pid,
2782
            frame,subframe,
2783 2784 2785 2786 2787 2788 2789 2790 2791
            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],
2792
            ret);
2793

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

2798
      eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
2799 2800
#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",
2801
            eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
2802
#endif
2803
      eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
2804

2805
      if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2806
#ifdef DEBUG_PHY_PROC
2807
        //if (((frame%10) == 0) || (frame < 50))
2808
        print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
2809
#endif
2810 2811 2812
        extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
                    eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
                    &eNB->UE_stats[i],
2813
                    fp->N_RB_DL,
2814
                    &rnti, &access_mode);
2815
        eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
2816

2817
      }
2818

2819
      if (eNB->ulsch[i]->Msg3_flag == 1)
2820
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
2821

2822
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
2823
        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),
2824
          T_INT(harq_pid));
2825

2826 2827 2828 2829
        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++;
2830

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

2833
        if (eNB->ulsch[i]->Msg3_flag == 1) {
2834
          LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
2835 2836
                eNB->Mod_id,
                eNB->CC_id,
2837
                frame,subframe, i,
2838
                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
2839
                fp->maxHARQ_Msg3Tx-1);
2840 2841

	  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",
2842
		eNB->Mod_id,harq_pid,
2843
		frame,subframe,
2844 2845 2846 2847 2848 2849 2850 2851 2852
		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],
2853 2854
		ret);

2855
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round ==
2856
              fp->maxHARQ_Msg3Tx) {
2857
            LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n",
2858
                  eNB->Mod_id, i);
2859
            eNB->UE_stats[i].mode = PRACH;
2860 2861 2862
	    if (eNB->mac_enabled==1) {
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
2863
					frame,
2864
					eNB->UE_stats[i].crnti);
2865
	    }
2866
            mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
2867

2868 2869
            eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
            //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0;
2870

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

2875
            get_Msg3_alloc_ret(fp,
2876
                               subframe,
2877
                               frame,
2878 2879
                               &eNB->ulsch[i]->Msg3_frame,
                               &eNB->ulsch[i]->Msg3_subframe);
2880 2881 2882
          }
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
2883

2884 2885
        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",
2886
                eNB->Mod_id,harq_pid,
2887
                frame,subframe, i,
2888 2889 2890 2891
                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]);
2892 2893 2894

#if defined(MESSAGE_CHART_GENERATOR_PHY)
          MSC_LOG_RX_DISCARDED_MESSAGE(
2895 2896 2897 2898 2899 2900 2901
				       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
				       );
2902
#endif
2903

2904
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) {
2905
            LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
2906
                  eNB->Mod_id,harq_pid,
2907
                  frame,subframe, i,
2908
                  eNB->ulsch[i]->Mlimit);
2909

2910 2911 2912 2913
            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++;
2914 2915

	    // indicate error to MAC
2916 2917
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
2918
			      frame,subframe,
2919
			      eNB->ulsch[i]->rnti,
2920 2921 2922
			      NULL,
			      0,
			      harq_pid,
2923
			      &eNB->ulsch[i]->Msg3_flag);
2924 2925 2926 2927
          }
        }
      }  // ulsch in error
      else {
2928 2929 2930



2931
        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),
2932 2933
          T_INT(harq_pid));

2934
        if (eNB->ulsch[i]->Msg3_flag == 1) {
2935
	  LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
2936
		eNB->Mod_id,harq_pid,
2937 2938
		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",
2939
		eNB->Mod_id,harq_pid,
2940
		frame,subframe,
2941 2942 2943 2944 2945 2946 2947 2948 2949
		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],
2950 2951 2952 2953
		ret);
	}
#if defined(MESSAGE_CHART_GENERATOR_PHY)
        MSC_LOG_RX_MESSAGE(
2954 2955 2956 2957 2958 2959
			   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
			   );
2960
#endif
2961
        for (j=0; j<fp->nb_antennas_rx; j++)
2962
          //this is the RSSI per RB
2963
          eNB->UE_stats[i].UL_rssi[j] =
2964
	    
2965 2966
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
                     (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
2967
                     fp->ofdm_symbol_size) -
2968 2969
            eNB->rx_total_gain_dB -
            hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
2970
            get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
2971
	    
2972 2973 2974 2975
        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;
2976

2977
        if (eNB->ulsch[i]->Msg3_flag == 1) {
2978
	  if (eNB->mac_enabled==1) {
2979

2980
	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
2981
		  eNB->Mod_id,
2982 2983
		  frame,harq_pid,i);
	    
2984 2985
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
2986
			      frame,subframe,
2987 2988 2989
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
2990
			      harq_pid,
2991
			      &eNB->ulsch[i]->Msg3_flag);
2992 2993
	    
	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
2994 2995
	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	      eNB->UE_stats[i].mode = PRACH;
2996 2997
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
2998
					frame,
2999 3000 3001
					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;
3002 3003 3004
	    } // Msg3_flag == 0
	    
	  } // mac_enabled==1
3005

3006 3007
          eNB->UE_stats[i].mode = PUSCH;
          eNB->ulsch[i]->Msg3_flag = 0;
3008

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

3011
          for (k=0; k<8; k++) { //harq_processes
3012 3013 3014 3015
            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;
3016
            }
3017

3018 3019 3020
            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;
3021

3022 3023 3024 3025 3026
            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;
3027
            }
3028 3029
          }

3030 3031 3032
          eNB->UE_stats[i].dlsch_sliding_cnt=0;
          eNB->UE_stats[i].dlsch_NAK_round0=0;
          eNB->UE_stats[i].dlsch_mcs_offset=0;
3033 3034 3035
        } // Msg3_flag==1
	else {  // Msg3_flag == 0

3036
#ifdef DEBUG_PHY_PROC
3037 3038
#ifdef DEBUG_ULSCH
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
3039
                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
3040

3041 3042
          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]);
3043 3044 3045

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

3048
	  if (eNB->mac_enabled==1) {
3049

3050 3051
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
3052
			      frame,subframe,
3053 3054 3055
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
3056 3057
			      harq_pid,
			      NULL);
3058

3059
#ifdef LOCALIZATION
3060 3061
	    start_meas(&eNB->localization_stats);
	    aggregate_eNB_UE_localization_stats(eNB,
3062 3063 3064
						i,
						frame,
						subframe,
3065 3066
						get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
	    stop_meas(&eNB->localization_stats);
3067
#endif
3068 3069 3070
	    
	  } // mac_enabled==1
        } // Msg3_flag == 0
3071

3072 3073
        // estimate timing advance for MAC
        if (abstraction_flag == 0) {
3074
          sync_pos = lte_est_timing_advance_pusch(eNB,i);
3075
          eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
3076
        }
3077

3078 3079
#ifdef DEBUG_PHY_PROC
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
3080
              eNB->Mod_id,
3081 3082
              frame, subframe,
              i,
3083
              eNB->UE_stats[i].timing_advance_update);
3084
#endif
3085 3086


3087 3088 3089
      }  // ulsch not in error

      // process HARQ feedback
3090
#ifdef DEBUG_PHY_PROC
3091
      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
3092
            eNB->dlsch[i][0]->rnti,
3093 3094
            frame,subframe,
            i);
3095
#endif
3096
      process_HARQ_feedback(i,
3097
                            eNB,proc,
3098 3099 3100 3101 3102 3103 3104
                            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",
3105
            eNB->Mod_id,frame,subframe,
3106
            eNB->UE_stats[i].sector,
3107 3108 3109
            harq_pid,
            i,
            ret,
3110 3111 3112 3113 3114
            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]);
3115 3116 3117 3118
#endif
      
      // dump stats to VCD
      if (i==0) {
3119 3120 3121
	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]);
3122
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
3123 3124
	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
3125
      }
3126
    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
3127

3128

3129
    // update ULSCH statistics for tracing
3130
    if ((frame % 100 == 0) && (subframe == 4)) {
3131
      for (harq_idx=0; harq_idx<8; harq_idx++) {
3132 3133 3134 3135 3136 3137 3138 3139
        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]);
3140
          } else {
3141
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
3142 3143
          }

3144 3145 3146 3147
          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];
3148
        }
3149 3150
      }
    }
3151

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3152
    if ((frame % 100 == 0) && (subframe==4)) {
3153
      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
3154
					eNB->UE_stats[i].total_TBS_last);
3155

3156
      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
3157
    }
3158

3159
    // CBA (non-LTE)
3160
    cba_procedures(eNB,proc,i,harq_pid,abstraction_flag);
3161 3162
  } // loop i=0 ... NUMBER_OF_UE_MAX-1

3163
  if (abstraction_flag == 0) {
3164
    lte_eNB_I0_measurements(eNB,
3165 3166
			    subframe,
			    0,
3167 3168
			    eNB->first_run_I0_measurements);
    eNB->first_run_I0_measurements = 0;
3169
  }
3170

3171
#ifdef PHY_ABSTRACTION
3172 3173 3174 3175
  else {
    lte_eNB_I0_measurements_emul(eNB,
				 0);
  }
3176

3177
#endif
3178 3179


3180
  //}
3181 3182

#ifdef EMOS
3183
  phy_procedures_emos_eNB_RX(subframe,eNB);
3184 3185
#endif

3186
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 0 );
3187

3188
  stop_meas(&eNB->phy_proc_rx);
3189

3190 3191 3192 3193
}

#undef DEBUG_PHY_PROC

3194 3195 3196 3197
#ifdef Rel10
int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type)
{

3198
  int do_proc=0;// do nothing
3199 3200

  switch(r_type) {
3201
  case no_relay:
3202
    do_proc= no_relay; // perform the normal eNB operation
3203
    break;
3204

3205
  case multicast_relay:
3206
    if (((next_slot >>1) < 6) || ((next_slot >>1) > 8))
3207
      do_proc = 0; // do nothing
3208 3209 3210
    else // SF#6, SF#7 and SF#8
      do_proc = multicast_relay; // do PHY procedures eNB TX

3211
    break;
3212

3213 3214
  default: // should'not be here
    LOG_W(PHY,"Not supported relay type %d, do nothing\n", r_type);
3215
    do_proc=0;
3216 3217
    break;
  }
3218

3219 3220
  return do_proc;
}
3221
#endif