phy_procedures_lte_eNb.c 108 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 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,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

308
  if (eNB->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,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

406
  if (eNB->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
    mch_pduP=NULL;
    break;
  }// switch
  
  if (mch_pduP) {
467
    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0);
468
    // Generate PMCH
469
    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload);
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) {
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
  // generate Cell-Specific Reference Signals for both slots
486
  if (eNB->abstraction_flag==0) {
487 488 489 490 491 492 493 494 495 496 497 498 499 500
    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
    if ((fp->frame_type == FDD) &&
505
	(eNB->abstraction_flag==0)) {
506 507 508 509 510 511 512 513 514 515 516 517 518
      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
      
    /// First half of SSS (TDD, slot 1)
    
    if ((fp->frame_type == TDD)&&
588
	(eNB->abstraction_flag==0)){
589 590 591 592 593 594
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   1);
    }
595

596
    /// generate PBCH
597
    if (eNB->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
  }
  else if ((subframe == 1) &&
	   (fp->frame_type == TDD)&&
614
	   (eNB->abstraction_flag==0)) {
615 616 617 618 619 620 621 622 623 624
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
  }
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
	   (fp->frame_type == FDD) &&
625
	   (eNB->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

  }

  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
	   (fp->frame_type == TDD) &&
642
	   (eNB->abstraction_flag==0)) {
643 644 645 646 647 648 649 650 651 652
    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) &&
653
	   (eNB->abstraction_flag==0)) {
654 655 656 657 658 659 660 661 662
    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
      
      
Cedric Roux's avatar
Cedric Roux committed
770 771 772 773
      T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
        T_INT(dci_alloc->rnti), T_INT(dci_alloc->format),
        T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid));

774
      eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
775
      
776
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"/%u\n",eNB->Mod_id,frame,subframe,
777
	    dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]);
778 779 780 781
      
#if defined(SMBV) 
      
      // configure UE-spec DCI
782 783
      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);
784
	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
785
      }
786 787 788 789 790
      
#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,
791
	    frame, subframe,UE_id,
792 793 794 795
	    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",
796
	    eNB->Mod_id,frame,dci_alloc->rnti);
Raymond Knopp's avatar
 
Raymond Knopp committed
797
    }
798 799 800
  }
  
}
801

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

804
  int harq_pid;
805
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
806
  int frame = proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
807
  int subframe = proc->subframe_tx;
808

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

868
}
869

870
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) {
871

872 873
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
874 875 876
  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;
877
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
878 879 880 881 882 883 884 885
  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,
886
	frame, subframe, input_buffer_length,
887 888 889 890 891
	get_G(fp,
	      dlsch_harq->nb_rb,
	      dlsch_harq->rb_alloc,
	      get_Qm(dlsch_harq->mcs),
	      dlsch_harq->Nl,
892
	      num_pdcch_symbols,frame,subframe),
893 894 895 896 897
	dlsch_harq->nb_rb,
	dlsch_harq->mcs,
	pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	dlsch_harq->rvidx,
	dlsch_harq->round);
898

899
#if defined(MESSAGE_CHART_GENERATOR_PHY)
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
  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]++;
925

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

993 994 995 996 997
    // 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);
    }
998

999
#endif
1000

1001

1002

1003 1004
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1005
    LOG_T(PHY,"eNB DLSCH SDU: \n");
1006

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

1009 1010
    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);
1011 1012


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

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

1028
  if (eNB->abstraction_flag==0) {
1029

1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
    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);
1066
	
1067 1068
    stop_meas(&eNB->dlsch_modulation_stats);
  }
1069 1070


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

1080
#endif
1081
  dlsch->active = 0;
1082
}
1083

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

1104 1105
  int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1;

1106 1107 1108
#if defined(SMBV) 
  // counts number of allocations in subframe
  // there is at least one allocation for PDCCH
1109 1110
  uint8_t smbv_alloc_cnt = 1;Exiting eNB thread RXn_TXnp4

1111
#endif
1112

1113 1114
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_DL)) return;

1115
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
1116
  start_meas(&eNB->phy_proc_tx);
1117

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

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

1140
  }
1141 1142 1143


  // Get scheduling info for next subframe
1144
  // This is called only for the CC_id = 0 and triggers scheduling for all CC_id's
1145 1146
  if (eNB->mac_enabled==1) {
    if (eNB->CC_id == 0) {
1147
      mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,frame,subframe);//,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1148
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1149
  }
1150

1151
  // clear the transmit data array for the current subframe
1152
  if (eNB->abstraction_flag==0) {
1153
    for (aa=0; aa<fp->nb_antennas_tx_eNB; aa++) {      
1154
      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
1155 1156 1157
             0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
    }
  }
1158

1159
  if (is_pmch_subframe(frame,subframe,fp)) {
1160
    pmch_procedures(eNB,proc,rn,r_type);
1161 1162 1163
  }
  else {
    // this is not a pmch subframe, so generate PSS/SSS/PBCH
1164
    common_signal_procedures(eNB,proc);
1165
  }
1166

1167
#if defined(SMBV) 
1168

Raymond Knopp's avatar
 
Raymond Knopp committed
1169
  // PBCH takes one allocation
1170
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
1171
    if (subframe==0)
Raymond Knopp's avatar
 
Raymond Knopp committed
1172 1173
      smbv_alloc_cnt++;
  }
1174

1175
#endif
1176

1177
  if (eNB->mac_enabled==1) {
1178 1179
    // Parse DCI received from MAC
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
1180 1181
    DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
				     eNB->CC_id,
1182
				     frame,
1183 1184 1185 1186
				     subframe);
  }
  else {
    DCI_pdu = &DCI_pdu_tmp;
1187
#ifdef EMOS_CHANNEL
1188
    fill_dci_emos(DCI_pdu,eNB);
1189
#else
1190
    fill_dci(DCI_pdu,eNB,proc);
1191
#endif
1192
  }
1193

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

1198 1199 1200
  if ((subframe_select(fp,ul_subframe)==SF_UL) ||
      (fp->frame_type == FDD)) {
    harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
1201

1202
    // clear DCI allocation maps for new subframe
1203
    for (i=0; i<NUMBER_OF_UE_MAX; i++)
1204 1205 1206
      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
1207 1208
      }
  }
1209

Raymond Knopp's avatar
 
Raymond Knopp committed
1210
  // clear previous allocation information for all UEs
1211
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
1212 1213
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1214
  }
1215 1216


1217
  num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
Raymond Knopp's avatar
Raymond Knopp committed
1218
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
1219 1220
        DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);

1221
#if defined(SMBV) 
Raymond Knopp's avatar
 
Raymond Knopp committed
1222
  // Sets up PDCCH and DCI table
1223 1224
  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);
1225
    dump_dci(fp,&DCI_pdu->dci_alloc[0]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1226 1227
    smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
  }
1228 1229
#endif

1230 1231
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);

1232
  // loop over all DCIs for this subframe to generate DLSCH allocations
1233 1234 1235 1236 1237
  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);
1238
    dci_alloc = &DCI_pdu->dci_alloc[i];
1239

1240 1241 1242 1243
    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);
1244 1245
      else
	UE_id = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1246
    }
1247 1248
    else UE_id=0;
    
1249
    generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
1250

Raymond Knopp's avatar
 
Raymond Knopp committed
1251
  }
1252

1253 1254
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

Raymond Knopp's avatar
 
Raymond Knopp committed
1255
  // Apply physicalConfigDedicated if needed
1256 1257 1258 1259
  // 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
1260
  for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
Cedric Roux's avatar
Cedric Roux committed
1261 1262
    dci_alloc = &DCI_pdu->dci_alloc[i];

1263 1264 1265
    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);
1266 1267
      else
	UE_id = i;
1268
      
1269
      if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
1270
	LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
1271
	mac_xface->macphy_exit("FATAL\n"); 
1272
      }
1273
      generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1274
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1275
  }
1276

1277 1278


Lionel Gauthier's avatar
Lionel Gauthier committed
1279 1280


Raymond Knopp's avatar
 
Raymond Knopp committed
1281 1282
  // 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
1283

1284 1285

  } else { // for emulation!!
1286 1287
    eNB->num_ue_spec_dci[(subframe)&1]=0;
    eNB->num_common_dci[(subframe)&1]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1288
  }
1289

1290
  if (eNB->abstraction_flag == 0) {
1291

1292
    if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) {
1293
      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,
1294
            DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
1295 1296
    }

1297 1298 1299 1300 1301 1302

    num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_ue_spec_dci,
                                         DCI_pdu->Num_common_dci,
                                         DCI_pdu->dci_alloc,
                                         0,
                                         AMP,
1303
                                         fp,
1304
                                         eNB->common_vars.txdataF[0],
1305
                                         subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1306

Raymond Knopp's avatar
 
Raymond Knopp committed
1307
  }
1308

1309
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
Raymond Knopp's avatar
 
Raymond Knopp committed
1310
  else {
1311
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
1312
    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
1313
  }
1314

1315 1316
#endif

1317
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
1318

Raymond Knopp's avatar
 
Raymond Knopp committed
1319
  // Check for SI activity
1320

1321
  if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
1322

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

1325
#if defined(SMBV) 
1326

Raymond Knopp's avatar
 
Raymond Knopp committed
1327
    // Configures the data source of allocation (allocation is configured by DCI)
1328 1329
    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
1330 1331
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
    }
1332

1333
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1334
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1335

Raymond Knopp's avatar
 
Raymond Knopp committed
1336
  // Check for RA activity
1337
  if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
1338

1339
#if defined(SMBV) 
1340

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

1369
	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);
1370 1371


Raymond Knopp's avatar
 
Raymond Knopp committed
1372
      }
Lionel Gauthier's avatar
Lionel Gauthier committed
1373

1374 1375 1376
      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)) {
1377

1378 1379
	// 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
1380
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1381
    }
1382

1383 1384


Raymond Knopp's avatar
 
Raymond Knopp committed
1385
  // if we have PHICH to generate
1386

1387
  if (is_phich_subframe(fp,subframe))
1388 1389 1390 1391
    {
      generate_phich_top(eNB,
			 proc,
			 AMP,
1392
			 0);
1393
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1394

1395 1396


1397
#ifdef EMOS
1398
  phy_procedures_emos_eNB_TX(subframe, eNB);
1399
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1400

1401
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
1402
  stop_meas(&eNB->phy_proc_tx);
1403
  
1404 1405
}

1406
void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid)
1407
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1408
  // this prepares the demodulation of the first PUSCH of a new user, containing Msg3
1409 1410
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1411

Raymond Knopp's avatar
 
Raymond Knopp committed
1412
  LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
1413
        eNB->Mod_id,
1414
        frame,subframe,
1415 1416 1417 1418
        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;
1419

1420 1421 1422
  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))   {
1423

1424
    //    harq_pid = 0;
1425

1426 1427 1428
    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
1429
    LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
1430
          eNB->Mod_id,
1431
          frame,subframe,UE_id);
1432 1433 1434 1435 1436 1437 1438 1439 1440
  }
}


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

1441
void process_HARQ_feedback(uint8_t UE_id,
1442
                           PHY_VARS_eNB *eNB,
1443
			   eNB_rxtx_proc_t *proc,
1444 1445 1446 1447 1448
                           uint8_t pusch_flag,
                           uint8_t *pucch_payload,
                           uint8_t pucch_sel,
                           uint8_t SR_payload)
{
1449

1450
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1451
  uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe;
1452 1453
  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];
1454
  LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
1455
  uint8_t subframe_m4,M,m;
1456 1457
  int mp;
  int all_ACKed=1,nb_alloc=0,nb_ACK=0;
1458 1459
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1460
  int harq_pid = subframe2harq_pid( fp,frame,subframe);
1461

1462 1463

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

1466 1467
    dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
    M=1;
1468

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

Lionel Gauthier's avatar
Lionel Gauthier committed
1485 1486 1487

#if defined(MESSAGE_CHART_GENERATOR_PHY)
    MSC_LOG_RX_MESSAGE(
1488 1489 1490 1491 1492 1493 1494 1495 1496 1497
		       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
1498
#endif
1499 1500
  } else { // TDD Handle M=1,2 cases only

1501
    M=ul_ACK_subframe2_M(fp,
1502 1503
                         subframe);

1504 1505 1506 1507 1508 1509 1510 1511
    // 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

1512
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1513
      dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling)
1514
	?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];
1515
    }
1516

1517
    else {  // PUCCH ACK/NAK
1518 1519 1520 1521 1522 1523 1524 1525 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
      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;
        }
1553
      }
1554
    }
1555 1556 1557 1558
  }

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

    for (m=0; m<M; m++) {
1562
      dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1563 1564
						 subframe,
						 m);
1565 1566 1567

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

1570 1571
    if (nb_alloc == nb_ACK)
      all_ACKed = 1;
1572
    else
1573
      all_ACKed = 0;
1574 1575 1576
  }


1577
  for (m=0,mp=-1; m<M; m++) {
1578

1579
    dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1580 1581
					       subframe,
					       m);
1582

1583 1584
    if (dlsch->subframe_tx[dl_subframe]==1) {
      if (pusch_flag == 1)
1585
        mp++;
1586
      else
1587
        mp = m;
1588

1589
      dl_harq_pid[m]     = dlsch->harq_ids[dl_subframe];
1590

1591
      if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
1592 1593 1594 1595
        if ((SR_payload == 1)&&(all_ACKed == 1))
          dlsch_ACK[m] = 1;
        else
          dlsch_ACK[m] = 0;
1596
      }
1597

1598
      if (dl_harq_pid[m]<dlsch->Mdlharq) {
1599 1600
        dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
1601
        LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id,
1602 1603 1604 1605 1606 1607 1608 1609 1610
              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");

1611
#endif
1612 1613 1614 1615 1616 1617 1618 1619

        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
1620
            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,
1621
                  dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
1622
#endif
1623

1624
            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),
1625
              T_INT(dl_harq_pid[m]));
1626

1627 1628 1629 1630 1631 1632 1633 1634 1635
            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++;

1636

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

1649 1650 1651 1652 1653 1654 1655
              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
1656
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
1657
                  dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
1658
#endif
1659

1660
            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),
1661
              T_INT(dl_harq_pid[m]));
1662

1663 1664 1665 1666 1667 1668 1669 1670
            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 +
1671
	      eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1672 1673
            /*
              ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
1674
              eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
            */
          }

          // 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);
1689
#endif
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711

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


        }
1712
      }
1713
    }
1714 1715 1716
  }
}

1717
void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
1718
		      eNB_rxtx_proc_t *proc,
1719 1720 1721 1722 1723 1724
                      uint8_t UE_id,
                      int16_t *n1_pucch0,
                      int16_t *n1_pucch1,
                      int16_t *n1_pucch2,
                      int16_t *n1_pucch3)
{
1725

1726
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
1727
  uint8_t nCCE0,nCCE1;
1728
  int sf;
1729 1730
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1731 1732

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

1735 1736
    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];
1737
      *n1_pucch1 = -1;
1738
    } else {
1739 1740 1741
      *n1_pucch0 = -1;
      *n1_pucch1 = -1;
    }
1742
  } else {
1743

1744 1745 1746
    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
1747
        /*  if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
1748 1749 1750 1751 1752
	    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;*/
1753

1754 1755
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1756 1757 1758 1759 1760 1761 1762
          *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

1763 1764
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1765 1766 1767 1768 1769 1770 1771 1772 1773
          *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;
1774 1775
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1776 1777 1778 1779 1780 1781 1782
          *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;
1783 1784
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4];
1785 1786 1787 1788 1789 1790 1791
          *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",
1792
              eNB->Mod_id,
1793 1794 1795
              frame,
              subframe,frame_parms->tdd_config);
        return;
1796
      }
1797

1798
      break;
1799

1800 1801
    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)
1802 1803
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
1804 1805 1806 1807
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1808 1809
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1810 1811 1812 1813 1814
          *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",
1815
              eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7],eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]);
1816

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

1824 1825
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7];
1826 1827 1828 1829 1830
          *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
1831 1832
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1833 1834 1835 1836
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1837 1838
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1839 1840 1841 1842 1843
          *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",
1844
              eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
1845
        return;
1846
      }
1847

1848
      break;
1849 1850
    }  // switch tdd_config

1851 1852 1853
    // Don't handle the case M>2
    *n1_pucch2 = -1;
    *n1_pucch3 = -1;
1854 1855 1856
  }
}

1857
void prach_procedures(PHY_VARS_eNB *eNB) {
1858

1859
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1860 1861 1862 1863
  uint16_t preamble_energy_list[64],preamble_delay_list[64];
  uint16_t preamble_max,preamble_energy_max;
  uint16_t i;
  int8_t UE_id;
1864 1865
  int subframe = eNB->proc.subframe_prach;
  int frame = eNB->proc.frame_prach;
1866
  uint8_t CC_id = eNB->CC_id;
1867

1868
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
1869 1870
  memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
  memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
1871

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

1876

1877
    rx_prach(eNB,
1878 1879 1880 1881 1882 1883 1884
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
  } else {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {

1885
      LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
1886
            UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
1887
            PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
1888
            fp->prach_config_common.rootSequenceIndex,
1889 1890
            PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex);

Raymond Knopp's avatar
 
Raymond Knopp committed
1891
      if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) &&
1892
          (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex ==
1893
           fp->prach_config_common.rootSequenceIndex) ) {
1894 1895 1896
        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;

1897
      }
1898
    }
1899
  }
1900

1901 1902 1903
  preamble_energy_max = preamble_energy_list[0];
  preamble_max = 0;

1904
  for (i=1; i<64; i++) {
1905 1906 1907 1908
    if (preamble_energy_max < preamble_energy_list[i]) {
      preamble_energy_max = preamble_energy_list[i];
      preamble_max = i;
    }
1909 1910 1911
  }

#ifdef DEBUG_PHY_PROC
1912
  LOG_D(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
1913 1914 1915
        preamble_max,
        preamble_energy_list[preamble_max],
        preamble_delay_list[preamble_max]);
1916 1917
#endif

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

1920
    UE_id = find_next_ue_index(eNB);
1921
 
1922
    if (UE_id>=0) {
1923
      eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
1924

1925
      eNB->UE_stats[(uint32_t)UE_id].sector = 0;
1926
      LOG_I(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",
1927 1928
            eNB->Mod_id,
            eNB->CC_id,
1929 1930
            frame,
            subframe,
1931
	    UE_id,
1932 1933 1934 1935
            preamble_max,
            preamble_energy_max/10,
            preamble_energy_max%10,
            preamble_delay_list[preamble_max]);
1936

1937
      if (eNB->mac_enabled==1) {
1938 1939
        uint8_t update_TA=4;

1940
        switch (fp->N_RB_DL) {
1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957
        case 6:
          update_TA = 16;
          break;

        case 25:
          update_TA = 4;
          break;

        case 50:
          update_TA = 2;
          break;

        case 100:
          update_TA = 1;
          break;
        }

1958 1959 1960 1961 1962 1963
	mac_xface->initiate_ra_proc(eNB->Mod_id,
				    eNB->CC_id,
				    frame,
				    preamble_max,
				    preamble_delay_list[preamble_max]*update_TA,
				    0,subframe,0);
1964 1965
      }      

1966
    } else {
1967
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many");
1968
      LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
1969
            eNB->Mod_id,frame, subframe);
1970
    }
1971
  }
1972
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
1973 1974
}

1975
void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1976

1977
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1978
  uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0};
1979 1980 1981
  int16_t n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3;
  uint8_t do_SR = 0;
  uint8_t pucch_sel = 0;
1982
  int32_t metric0=0,metric1=0,metric0_SR=0;
1983 1984
  ANFBmode_t bundling_flag;
  PUCCH_FMT_t format;
1985 1986
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
1987

1988 1989 1990
  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)) { 
1991

1992
    // check SR availability
1993 1994 1995
    do_SR = is_SR_subframe(eNB,proc,UE_id);
    //      do_SR = 0;
    
1996 1997
    // Now ACK/NAK
    // First check subframe_tx flag for earlier subframes
1998

1999 2000 2001 2002 2003 2004 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
    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++;
2046 2047


2048
	if (eNB->abstraction_flag == 0)
2049 2050 2051 2052 2053 2054 2055
	  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,
2056
				frame,
2057 2058 2059
				subframe,
				PUCCH1_THRES);
	
2060
#ifdef PHY_ABSTRACTION
2061 2062
	else {
	  metric0_SR = rx_pucch_emul(eNB,
2063
				     proc,
2064 2065 2066 2067 2068 2069 2070 2071
				     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);
	}
	
2072
#endif
2073

2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092
	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);
2093
	  }
2094 2095 2096 2097
	}
      }// do_SR==1
      
      if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR
2098
      } else if (eNB->frame_parms.frame_type==FDD) { // FDD
2099 2100 2101 2102 2103
	// 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);
	
2104
	if (eNB->abstraction_flag == 0) {
2105 2106 2107 2108 2109 2110 2111 2112 2113 2114
	  
	  
	  
	  metric0 = rx_pucch(eNB,
			     pucch_format1a,
			     UE_id,
			     (uint16_t)n1_pucch0,
			     0, //n2_pucch
			     0, // shortened format
			     pucch_payload0,
2115
			     frame,
2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126
			     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,
2127
			     frame,
2128 2129
			     subframe,
			     PUCCH1a_THRES);
2130
	  
2131
	}
2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148
	
	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);
      
2149
      if (eNB->abstraction_flag == 0) {
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
	
	
	
	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 {
2177
#ifdef PHY_ABSTRACTION
2178 2179 2180 2181 2182 2183
	metric0 = rx_pucch_emul(eNB,
				proc,
				UE_id,
				pucch_format1a,
				0,
				pucch_payload0);
2184
#endif
2185
      }
2186
	
2187
#ifdef DEBUG_PHY_PROC
2188 2189 2190 2191 2192
      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);
2193
#endif
2194
	
2195 2196 2197 2198 2199
      process_HARQ_feedback(UE_id,eNB,proc,
			    0,// pusch_flag
			    pucch_payload0,
			    2,
			    SR_payload);
2200

2201 2202
    } // FDD
    else {  //TDD
2203

2204
      bundling_flag = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode;
2205

2206
      // fix later for 2 TB case and format1b
Raymond Knopp's avatar
Raymond Knopp committed
2207

2208 2209 2210 2211 2212 2213 2214
      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;
      }
2215

2216 2217
      // if SR was detected, use the n1_pucch from SR
      if (SR_payload==1) {
2218
#ifdef DEBUG_PHY_PROC
2219 2220 2221 2222
	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);
2223
#endif
2224

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

2280 2281
	// Check n1_pucch1 metric
	if (n1_pucch1 != -1) {
2282
	  if (eNB->abstraction_flag == 0)
2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
	    metric1 = rx_pucch(eNB,
			       format,
			       UE_id,
			       (uint16_t)n1_pucch1,
			       0, //n2_pucch
			       0, // shortened format
			       pucch_payload1,
			       frame,
			       subframe,
			       PUCCH1a_THRES);
	  else {
2294
#ifdef PHY_ABSTRACTION
2295 2296 2297 2298 2299 2300
	    metric1 = rx_pucch_emul(eNB,
				    proc,
				    UE_id,
				    format,
				    1,
				    pucch_payload1);
2301
#endif
2302 2303 2304
	  }
	}
      }
2305

2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320
      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
2321
      }
2322

2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333
#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);
2334
    }
2335
  }  
2336
}
2337

2338

2339
void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
2340

2341 2342
  uint8_t access_mode;
  int num_active_cba_groups;
2343 2344
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2345 2346
  uint16_t rnti=0;
  int ret=0;
2347
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2348

2349 2350
  if (eNB->ulsch[UE_id]==NULL) return;

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

2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
    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;
2446 2447
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465
      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
2466 2467
	if ((eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) && 
	    (eNB->mac_enabled==1)) {
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
	  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
2496
  }
2497

2498
}
2499

2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616
typedef struct {
  PHY_VARS_eNB *eNB;
  int slot;
} fep_task;

void fep0(PHY_VARS_eNB *eNB,int slot) {

  eNB_proc_t *proc       = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  int l;

  remove_7_5_kHz(eNB,(slot&1)+(proc->subframe_rx<<1));
  for (l=0; l<fp->symbols_per_tti/2; l++) {
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		(slot&1)+(proc->subframe_rx<<1),
		0,
		0
		);
  }
}

static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) {

  if (pthread_mutex_lock(mutex) != 0) {
    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
    exit_fun("nothing to add");
    return(-1);
  }
  
  *instance_cnt=*instance_cnt-1;
  
  if (pthread_mutex_unlock(mutex) != 0) {
    LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name);
    exit_fun("nothing to add");
    return(-1);
  }
  return(0);
}

static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {

  if (pthread_mutex_lock(mutex) != 0) {
    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
    exit_fun("nothing to add");
    return(-1);
  }
  
  while (*instance_cnt < 0) {
    // most of the time the thread is waiting here
    // proc->instance_cnt_rxtx is -1
    pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again
  }

  if (pthread_mutex_unlock(mutex) != 0) {
    LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name);
    exit_fun("nothing to add");
    return(-1);
  }
  return(0);
}

extern int oai_exit;


static void *fep_thread(void *param) {

  PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param;
  eNB_proc_t *proc  = &eNB->proc;
  while (!oai_exit) {
    if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break;  
    fep0(eNB,0);
    if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
  }
  return(NULL);
}

void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) {

  eNB_proc_t *proc = &eNB->proc;

  proc->instance_cnt_fep         = -1;
    
  pthread_mutex_init( &proc->mutex_fep, NULL);
  pthread_cond_init( &proc->cond_fep, NULL);

  pthread_create(&proc->pthread_fep, attr_fep, fep_thread, (void*)eNB);

}

void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) {

  eNB_proc_t *proc = &eNB->proc;
  struct timespec wait;
  int wait_cnt=0;
  wait.tv_sec=0;
  wait.tv_nsec=5000000L;

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

  if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
    printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep);
    exit_fun( "error locking mutex_fep" );
    return;
  }

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

2617

2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640
  if (pthread_cond_signal(&proc->cond_fep) != 0) {
    printf("[eNB] ERROR pthread_cond_signal for fep thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return;
  }
  
  pthread_mutex_unlock( &proc->mutex_fep );

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

  if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
    printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep);
    exit_fun( "error locking mutex_fep" );
    return;
  }
  while (proc->instance_cnt_fep==0) {
    wait_cnt++;
    if (wait_cnt>10000)
      break;
  };

  pthread_mutex_unlock( &proc->mutex_fep );
2641
  if (wait_cnt>1000000) {
2642 2643 2644
    printf("[eNB] parallel FEP didn't finish\n");
    exit_fun( "error" );
  }
2645 2646

  stop_meas(&eNB->ofdm_demod_stats);
2647 2648
}

Raymond Knopp's avatar
Raymond Knopp committed
2649
void eNB_fep_full(PHY_VARS_eNB *eNB) {
2650

Raymond Knopp's avatar
Raymond Knopp committed
2651
  eNB_proc_t *proc = &eNB->proc;
2652
  int l;
2653
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2654

2655
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
2656
  start_meas(&eNB->ofdm_demod_stats);
2657 2658 2659 2660 2661 2662 2663
  remove_7_5_kHz(eNB,proc->subframe_rx<<1);
  remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1));
  for (l=0; l<fp->symbols_per_tti/2; l++) {
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		proc->subframe_rx<<1,
Raymond Knopp's avatar
Raymond Knopp committed
2664
		0,
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674
		0
		);
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		1+(proc->subframe_rx<<1),
		0,
		0
		);
  }
2675
  stop_meas(&eNB->ofdm_demod_stats);
2676 2677 2678 2679 2680 2681
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
  
  if (eNB->node_function == NGFI_RRU_IF4p5) {
    /// **** send_IF4 of rxdataF to RCC (no prach now) **** ///
    send_IF4p5(eNB, proc->frame_rx, proc->subframe_rx, IF4p5_PULFFT, 0);
Raymond Knopp's avatar
Raymond Knopp committed
2682
  }    
2683 2684
}

Raymond Knopp's avatar
Raymond Knopp committed
2685
void eNB_fep_rru_if5(PHY_VARS_eNB *eNB) {
2686

Raymond Knopp's avatar
Raymond Knopp committed
2687
  eNB_proc_t *proc=&eNB->proc;
2688 2689 2690 2691 2692 2693 2694 2695 2696
  uint8_t seqno=0;

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

}

Raymond Knopp's avatar
Raymond Knopp committed
2697
void do_prach(PHY_VARS_eNB *eNB) {
2698

Raymond Knopp's avatar
Raymond Knopp committed
2699
  eNB_proc_t *proc = &eNB->proc;
2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;

  // check if we have to detect PRACH first
  if (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0) { 
    /* accept some delay in processing - up to 5ms */
    int i;
    for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) {
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
      usleep(500);
    }
    if (proc->instance_cnt_prach == 0) {
      exit_fun( "PRACH thread busy" );
      return;
    }
    
    // wake up thread for PRACH RX
    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
      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;
    }
    
    ++proc->instance_cnt_prach;
    // set timing for prach thread
    proc->frame_prach = proc->frame_rx;
    proc->subframe_prach = proc->subframe_rx;
    
    // the thread can now be woken up
    if (pthread_cond_signal(&proc->cond_prach) != 0) {
      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index);
      exit_fun( "ERROR pthread_cond_signal" );
      return;
    }
    
    pthread_mutex_unlock( &proc->mutex_prach );
  }

}

void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){


Raymond Knopp's avatar
Raymond Knopp committed
2742 2743 2744 2745
  eNB_proc_t *proc       = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  const int subframe     = proc->subframe_rx;
  const int frame        = proc->frame_rx;
2746
  int offset             = (eNB->single_thread_flag==1) ? 0 : (subframe&1);
Sandeep Kumar's avatar
Sandeep Kumar committed
2747

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

Raymond Knopp's avatar
Raymond Knopp committed
2750 2751 2752
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB+offset, proc->frame_rx );
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+offset, proc->subframe_rx );
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 1 );
2753
  
2754
  start_meas(&eNB->phy_proc_rx);
2755
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe);
2756

Raymond Knopp's avatar
Raymond Knopp committed
2757

Raymond Knopp's avatar
Raymond Knopp committed
2758
  if (eNB->fep) eNB->fep(eNB);
2759

Raymond Knopp's avatar
Raymond Knopp committed
2760
  if (eNB->do_prach) eNB->do_prach(eNB);
2761

Raymond Knopp's avatar
Raymond Knopp committed
2762
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 0 );
2763 2764
}

2765

2766
void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type)
2767
{
2768
  //RX processing for ue-specific resources (i
2769
  UNUSED(r_type);
2770
  uint32_t ret=0,i,j,k;
2771 2772 2773 2774 2775
  uint32_t harq_pid, harq_idx, round;
  uint8_t nPRS;
  int sync_pos;
  uint16_t rnti=0;
  uint8_t access_mode;
2776
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2777

2778
  const int subframe = proc->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
2779 2780
  const int frame    = proc->frame_rx;
  int offset         = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1;
2781

2782

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

Raymond Knopp's avatar
Raymond Knopp committed
2785
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
2786

2787
#ifdef DEBUG_PHY_PROC
2788
  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
2789
#endif
2790

2791
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
2792

2793
  T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
Cedric Roux's avatar
Cedric Roux committed
2794
    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
2795
             eNB->frame_parms.samples_per_tti * 4));
2796

2797 2798 2799 2800
  eNB->rb_mask_ul[0]=0;
  eNB->rb_mask_ul[1]=0;
  eNB->rb_mask_ul[2]=0;
  eNB->rb_mask_ul[3]=0;
2801 2802 2803



2804
  // Check for active processes in current subframe
2805
  harq_pid = subframe2harq_pid(fp,
2806 2807 2808 2809
                               frame,subframe);

  // reset the cba flag used for collision detection
  for (i=0; i < NUM_MAX_CBA_GROUP; i++) {
2810
    eNB->cba_last_reception[i]=0;
2811 2812 2813 2814 2815
  }

  // Do PUCCH processing first

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2816
    pucch_procedures(eNB,proc,i,harq_pid);
2817
  }
2818

2819
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2820

2821
    // check for Msg3
2822
    if (eNB->mac_enabled==1) {
2823
      if (eNB->UE_stats[i].mode == RA_RESPONSE) {
2824
	process_Msg3(eNB,proc,i,harq_pid);
2825 2826
      }
    }
2827 2828


2829 2830 2831
    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;
2832

2833 2834 2835
    if ((eNB->ulsch[i]) &&
        (eNB->ulsch[i]->rnti>0) &&
        (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) {
2836
      // UE is has ULSCH scheduling
2837
      round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
2838
 
2839
      for (int rb=0;
2840
           rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
2841
	   rb++) {
2842
	int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
2843
	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
2844
      }
2845

2846

2847
      if (eNB->ulsch[i]->Msg3_flag == 1) {
2848
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
2849
              eNB->Mod_id,
2850 2851
              frame,
              subframe,
2852
              eNB->UE_stats[i].sector);
2853 2854
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1);
      } else {
2855

2856
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n",
2857
              eNB->Mod_id,
2858 2859 2860
              frame,
              subframe,
              i,
2861
              mode_string[eNB->UE_stats[i].mode]);
2862
      }
2863 2864


2865
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
2866

2867
      eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
2868
				    nPRS)%12;
2869

2870
      if (fp->frame_type == FDD ) {
2871
        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
2872

2873 2874
        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
2875
        } else {
2876
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
2877
        }
2878
      }
2879

2880 2881
      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",
2882
            eNB->Mod_id,harq_pid,frame,subframe,
2883 2884 2885 2886 2887 2888 2889 2890 2891 2892
            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,
2893
            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
2894
            nPRS,
2895 2896 2897 2898
            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;
2899
      start_meas(&eNB->ulsch_demodulation_stats);
2900

2901
      if (eNB->abstraction_flag==0) {
2902
        rx_ulsch(eNB,proc,
2903
                 eNB->UE_stats[i].sector,  // this is the effective sector id
2904
                 i,
2905
                 eNB->ulsch,
2906 2907
                 0);
      }
2908

2909 2910
#ifdef PHY_ABSTRACTION
      else {
2911
        rx_ulsch_emul(eNB,proc,
2912
                      eNB->UE_stats[i].sector,  // this is the effective sector id
2913 2914
                      i);
      }
2915

2916
#endif
2917
      stop_meas(&eNB->ulsch_demodulation_stats);
2918

2919

2920
      start_meas(&eNB->ulsch_decoding_stats);
2921

2922
      if (eNB->abstraction_flag == 0) {
2923
        ret = ulsch_decoding(eNB,proc,
2924 2925
                             i,
                             0, // control_only_flag
2926 2927
                             eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
			     eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2928
      }
2929

2930 2931
#ifdef PHY_ABSTRACTION
      else {
2932 2933
        ret = ulsch_decoding_emul(eNB,
				  proc,
2934 2935 2936
                                  i,
                                  &rnti);
      }
2937

2938
#endif
2939
      stop_meas(&eNB->ulsch_decoding_stats);
2940

2941
      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",
2942
            eNB->Mod_id,harq_pid,
2943
            frame,subframe,
2944 2945 2946 2947 2948 2949 2950 2951 2952
            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],
2953
            ret);
2954

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

2959
      eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
2960 2961
#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",
2962
            eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
2963
#endif
2964
      eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
2965

2966
      if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2967
#ifdef DEBUG_PHY_PROC
2968
        //if (((frame%10) == 0) || (frame < 50))
2969
        print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
2970
#endif
2971 2972 2973
        extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
                    eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
                    &eNB->UE_stats[i],
2974
                    fp->N_RB_DL,
2975
                    &rnti, &access_mode);
2976
        eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
2977

2978
      }
2979

2980
      if (eNB->ulsch[i]->Msg3_flag == 1)
2981
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
2982

2983
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
2984
        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),
2985
          T_INT(harq_pid));
2986

2987 2988 2989 2990
        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++;
2991

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

2994
        if (eNB->ulsch[i]->Msg3_flag == 1) {
2995
          LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
2996 2997
                eNB->Mod_id,
                eNB->CC_id,
2998
                frame,subframe, i,
2999
                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
3000
                fp->maxHARQ_Msg3Tx-1);
3001 3002

	  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",
3003
		eNB->Mod_id,harq_pid,
3004
		frame,subframe,
3005 3006 3007 3008 3009 3010 3011 3012 3013
		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],
3014 3015
		ret);

3016
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round ==
3017
              fp->maxHARQ_Msg3Tx) {
3018
            LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n",
3019
                  eNB->Mod_id, i);
3020
            eNB->UE_stats[i].mode = PRACH;
3021 3022 3023
	    if (eNB->mac_enabled==1) {
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3024
					frame,
3025
					eNB->UE_stats[i].crnti);
3026
	    }
3027
            mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
3028

3029 3030
            eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
            //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0;
3031

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

3036
            get_Msg3_alloc_ret(fp,
3037
                               subframe,
3038
                               frame,
3039 3040
                               &eNB->ulsch[i]->Msg3_frame,
                               &eNB->ulsch[i]->Msg3_subframe);
3041 3042 3043
          }
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
3044

3045 3046
        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",
3047
                eNB->Mod_id,harq_pid,
3048
                frame,subframe, i,
3049 3050 3051 3052
                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]);
3053 3054 3055

#if defined(MESSAGE_CHART_GENERATOR_PHY)
          MSC_LOG_RX_DISCARDED_MESSAGE(
3056 3057 3058 3059 3060 3061 3062
				       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
				       );
3063
#endif
3064

3065
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) {
3066
            LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
3067
                  eNB->Mod_id,harq_pid,
3068
                  frame,subframe, i,
3069
                  eNB->ulsch[i]->Mlimit);
3070

3071 3072 3073 3074
            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++;
3075 3076

	    // indicate error to MAC
3077 3078 3079 3080 3081 3082 3083 3084 3085
	    if (eNB->mac_enabled == 1)
	      mac_xface->rx_sdu(eNB->Mod_id,
				eNB->CC_id,
				frame,subframe,
				eNB->ulsch[i]->rnti,
				NULL,
				0,
				harq_pid,
				&eNB->ulsch[i]->Msg3_flag);
3086 3087 3088 3089
          }
        }
      }  // ulsch in error
      else {
3090 3091 3092



3093
        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),
3094 3095
          T_INT(harq_pid));

3096
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3097
	  LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
3098
		eNB->Mod_id,harq_pid,
3099 3100
		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",
3101
		eNB->Mod_id,harq_pid,
3102
		frame,subframe,
3103 3104 3105 3106 3107 3108 3109 3110 3111
		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],
3112 3113 3114 3115
		ret);
	}
#if defined(MESSAGE_CHART_GENERATOR_PHY)
        MSC_LOG_RX_MESSAGE(
3116 3117 3118 3119 3120 3121
			   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
			   );
3122
#endif
3123
        for (j=0; j<fp->nb_antennas_rx; j++)
3124
          //this is the RSSI per RB
3125
          eNB->UE_stats[i].UL_rssi[j] =
3126
	    
3127 3128
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
                     (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
3129
                     fp->ofdm_symbol_size) -
3130 3131
            eNB->rx_total_gain_dB -
            hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
3132
            get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
3133
	    
3134 3135 3136 3137
        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;
3138

3139
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3140
	  if (eNB->mac_enabled==1) {
3141

3142
	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
3143
		  eNB->Mod_id,
3144
		  frame,harq_pid,i);
3145 3146 3147 3148 3149 3150 3151 3152 3153
	    if (eNB->mac_enabled)
	      mac_xface->rx_sdu(eNB->Mod_id,
				eNB->CC_id,
				frame,subframe,
				eNB->ulsch[i]->rnti,
				eNB->ulsch[i]->harq_processes[harq_pid]->b,
				eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
				harq_pid,
				&eNB->ulsch[i]->Msg3_flag);
3154 3155
	    
	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
3156 3157
	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	      eNB->UE_stats[i].mode = PRACH;
3158 3159
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3160
					frame,
3161 3162 3163
					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;
3164 3165 3166
	    } // Msg3_flag == 0
	    
	  } // mac_enabled==1
3167

3168 3169
          eNB->UE_stats[i].mode = PUSCH;
          eNB->ulsch[i]->Msg3_flag = 0;
3170

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

3173
          for (k=0; k<8; k++) { //harq_processes
3174 3175 3176 3177
            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;
3178
            }
3179

3180 3181 3182
            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;
3183

3184 3185 3186 3187 3188
            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;
3189
            }
3190 3191
          }

3192 3193 3194
          eNB->UE_stats[i].dlsch_sliding_cnt=0;
          eNB->UE_stats[i].dlsch_NAK_round0=0;
          eNB->UE_stats[i].dlsch_mcs_offset=0;
3195 3196 3197
        } // Msg3_flag==1
	else {  // Msg3_flag == 0

3198
#ifdef DEBUG_PHY_PROC
3199 3200
#ifdef DEBUG_ULSCH
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
3201
                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
3202

3203 3204
          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]);
3205 3206 3207

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

3210
	  if (eNB->mac_enabled==1) {
3211

3212 3213
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
3214
			      frame,subframe,
3215 3216 3217
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
3218 3219
			      harq_pid,
			      NULL);
3220

3221
#ifdef LOCALIZATION
3222 3223
	    start_meas(&eNB->localization_stats);
	    aggregate_eNB_UE_localization_stats(eNB,
3224 3225 3226
						i,
						frame,
						subframe,
3227 3228
						get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
	    stop_meas(&eNB->localization_stats);
3229
#endif
3230 3231 3232
	    
	  } // mac_enabled==1
        } // Msg3_flag == 0
3233

3234
        // estimate timing advance for MAC
3235
        if (eNB->abstraction_flag == 0) {
3236
          sync_pos = lte_est_timing_advance_pusch(eNB,i);
3237
          eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
3238
        }
3239

3240 3241
#ifdef DEBUG_PHY_PROC
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
3242
              eNB->Mod_id,
3243 3244
              frame, subframe,
              i,
3245
              eNB->UE_stats[i].timing_advance_update);
3246
#endif
3247 3248


3249 3250 3251
      }  // ulsch not in error

      // process HARQ feedback
3252
#ifdef DEBUG_PHY_PROC
3253
      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
3254
            eNB->dlsch[i][0]->rnti,
3255 3256
            frame,subframe,
            i);
3257
#endif
3258
      process_HARQ_feedback(i,
3259
                            eNB,proc,
3260 3261 3262 3263 3264 3265 3266
                            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",
3267
            eNB->Mod_id,frame,subframe,
3268
            eNB->UE_stats[i].sector,
3269 3270 3271
            harq_pid,
            i,
            ret,
3272 3273 3274 3275 3276
            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]);
3277 3278 3279 3280
#endif
      
      // dump stats to VCD
      if (i==0) {
3281 3282 3283
	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]);
3284
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
3285 3286
	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
3287
      }
3288
    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
3289

3290

3291
    // update ULSCH statistics for tracing
3292
    if ((frame % 100 == 0) && (subframe == 4)) {
3293
      for (harq_idx=0; harq_idx<8; harq_idx++) {
3294 3295 3296 3297 3298 3299 3300 3301
        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]);
3302
          } else {
3303
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
3304 3305
          }

3306 3307 3308 3309
          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];
3310
        }
3311 3312
      }
    }
3313

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3314
    if ((frame % 100 == 0) && (subframe==4)) {
3315
      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
3316
					eNB->UE_stats[i].total_TBS_last);
3317

3318
      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
3319
    }
3320

3321
    // CBA (non-LTE)
3322
    cba_procedures(eNB,proc,i,harq_pid);
3323 3324
  } // loop i=0 ... NUMBER_OF_UE_MAX-1

3325
  if (eNB->abstraction_flag == 0) {
3326
    lte_eNB_I0_measurements(eNB,
3327 3328
			    subframe,
			    0,
3329 3330
			    eNB->first_run_I0_measurements);
    eNB->first_run_I0_measurements = 0;
3331
  }
3332

3333
#ifdef PHY_ABSTRACTION
3334 3335 3336 3337
  else {
    lte_eNB_I0_measurements_emul(eNB,
				 0);
  }
3338

3339
#endif
3340 3341


3342
  //}
3343 3344

#ifdef EMOS
3345
  phy_procedures_emos_eNB_RX(subframe,eNB);
3346 3347
#endif

Raymond Knopp's avatar
Raymond Knopp committed
3348
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
3349

3350
  stop_meas(&eNB->phy_proc_rx);
3351

3352 3353 3354 3355
}

#undef DEBUG_PHY_PROC

3356 3357 3358 3359
#ifdef Rel10
int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type)
{

3360
  int do_proc=0;// do nothing
3361 3362

  switch(r_type) {
3363
  case no_relay:
3364
    do_proc= no_relay; // perform the normal eNB operation
3365
    break;
3366

3367
  case multicast_relay:
3368
    if (((next_slot >>1) < 6) || ((next_slot >>1) > 8))
3369
      do_proc = 0; // do nothing
3370 3371 3372
    else // SF#6, SF#7 and SF#8
      do_proc = multicast_relay; // do PHY procedures eNB TX

3373
    break;
3374

3375 3376
  default: // should'not be here
    LOG_W(PHY,"Not supported relay type %d, do nothing\n", r_type);
3377
    do_proc=0;
3378 3379
    break;
  }
3380

3381 3382
  return do_proc;
}
3383
#endif