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

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

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

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

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

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

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

53 54
#include "T.h"

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

58 59
#include <time.h>

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

64

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

72 73 74 75 76 77
//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

78 79
void exit_fun(const char* s);

80
extern int exit_openair;
81 82
struct timespec start_fh, start_fh_prev;
int start_fh_sf, start_fh_prev_sf;
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
int harq_pid_updated[NUMBER_OF_UE_MAX][8] = {{0}};
int harq_pid_round[NUMBER_OF_UE_MAX][8] = {{0}};

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

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

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

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

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

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

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

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

  return(0);
}
144

145

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

150 151

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

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

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

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

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

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

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

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

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

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

233 234 235
  return(-1);
}

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

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

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

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

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

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

267 268 269 270 271
    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;
272
      *round = 0;
273 274 275
    } else {
      printf("%s:%d: bad state for harq process - PLEASE REPORT!!\n", __FILE__, __LINE__);
      abort();
276
    }
277
  } else { // This is a UL request
278

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

290 291 292
  return(0);
}

Cedric Roux's avatar
Cedric Roux committed
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
int get_ue_rbs(int Mod_id, int CC_id, int rnti, int frame, int subframe, int *start_rb, int *nb_rb)
{
  LTE_eNB_ULSCH_t *ULSCH_ptr;
  uint8_t ulsch_subframe,ulsch_frame;
  int8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]);
  int harq_pid;

  if (UE_id==-1) {
    LOG_E(PHY,"Cannot find UE with rnti %x (Mod_id %d, CC_id %d)\n",rnti, Mod_id, CC_id);
    return(-1);
  }

  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);
  harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,
                                ulsch_frame,
                                ulsch_subframe);
  *nb_rb    = ULSCH_ptr->harq_processes[harq_pid]->nb_rb;
  *start_rb = ULSCH_ptr->harq_processes[harq_pid]->first_rb;

  return(0);
}

317
int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
318
{
319
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
320 321
}

322 323
int16_t get_target_pucch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
{
324
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
325 326
}

327
#ifdef EMOS
328
void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB)
329
{
330 331 332 333

}
#endif

334
void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type)
335 336
{
  UNUSED(r_type);
337
  int subframe = proc->subframe_rx;
338

339
#ifdef DEBUG_PHY_PROC
340
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", eNB->Mod_id,proc->frame_rx, subframe);
341
#endif
342

343

344
  if (eNB->abstraction_flag == 0) {
345
    lte_eNB_I0_measurements(eNB,
346
			    subframe,
347
                            0,
348
                            eNB->first_run_I0_measurements);
Raymond Knopp's avatar
 
Raymond Knopp committed
349
  }
350

351
#ifdef PHY_ABSTRACTION
Raymond Knopp's avatar
 
Raymond Knopp committed
352
  else {
353
    lte_eNB_I0_measurements_emul(eNB,
354
                                 0);
355
  }
356

Raymond Knopp's avatar
 
Raymond Knopp committed
357 358
#endif

359

360 361
}

Raymond Knopp's avatar
 
Raymond Knopp committed
362 363


364
#ifdef EMOS
365
void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *eNB)
366 367
{

368 369
  uint8_t aa;
  uint16_t last_subframe_emos;
370
  uint16_t pilot_pos1 = 3 - eNB->frame_parms.Ncp, pilot_pos2 = 10 - 2*eNB->frame_parms.Ncp;
371
  uint32_t bytes;
372 373 374

  last_subframe_emos=0;

Raymond Knopp's avatar
 
Raymond Knopp committed
375

Raymond Knopp's avatar
 
Raymond Knopp committed
376

Raymond Knopp's avatar
 
Raymond Knopp committed
377

378
#ifdef EMOS_CHANNEL
379

380
  //if (last_slot%2==1) // this is for all UL subframes
381
  if (subframe==3)
382 383 384 385 386 387 388
    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));
389
    }
390

391 392
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
393
  if (subframe==4) {
394
    emos_dump_eNB.timestamp = rt_get_time_ns();
395 396 397 398 399
    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],
400
           sizeof(PHY_MEASUREMENTS_eNB));
401
    memcpy(&emos_dump_eNB.UE_stats[0],&eNB->UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats));
402 403

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

405 406
    //bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, "test", sizeof("test"));
    if (bytes!=sizeof(fifo_dump_emos_eNB)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
407
      LOG_W(PHY,"[eNB %d] Frame %d, subframe %d, Problem writing EMOS data to FIFO (bytes=%d, size=%d)\n",
408
            eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, subframe,bytes,sizeof(fifo_dump_emos_eNB));
409
    } else {
410
      if (eNB->proc[(subframe+1)%10].frame_tx%100==0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
411
        LOG_I(PHY,"[eNB %d] Frame %d (%d), subframe %d, Writing %d bytes EMOS data to FIFO\n",
412
              eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, ((fifo_dump_emos_eNB*)&emos_dump_eNB)->frame_tx, subframe, bytes);
413
      }
414
    }
415 416 417 418 419 420 421
  }
}
#endif


#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
#define AMP_OVER_2 (AMP>>1)
422 423
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)};
424

Lionel Gauthier's avatar
Lionel Gauthier committed
425

Raymond Knopp's avatar
 
Raymond Knopp committed
426

Cedric Roux's avatar
Cedric Roux committed
427
unsigned int taus(void);
428
DCI_PDU DCI_pdu_tmp;
Raymond Knopp's avatar
 
Raymond Knopp committed
429

430

431
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,relaying_type_t r_type) {
432 433


Cedric Roux's avatar
Cedric Roux committed
434
#if defined(Rel10) || defined(Rel14)
435 436
  MCH_PDU *mch_pduP;
  MCH_PDU  mch_pdu;
437
  //  uint8_t sync_area=255;
438
#endif
439

440
  int subframe = proc->subframe_tx;
441

442
  if (eNB->abstraction_flag==0) {
443 444
    // This is DL-Cell spec pilots in Control region
    generate_pilots_slot(eNB,
445
			 eNB->common_vars.txdataF[0],
446 447
			 AMP,
			 subframe<<1,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
448
  }
449
  
Cedric Roux's avatar
Cedric Roux committed
450
#if defined(Rel10) || defined(Rel14)
451 452 453 454
  // 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,
455
				    proc->frame_tx,
456 457 458 459 460 461
				    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",
462 463
	    eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs,
	    eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
464 465
    else {
      LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n",
466
	    eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->sync_area,
467 468
	    (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment");
      mch_pduP = NULL;
Lionel Gauthier's avatar
Lionel Gauthier committed
469
    }
470
    
Raymond Knopp's avatar
 
Raymond Knopp committed
471
    break;
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
    
  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
488
    } else {
489
      mch_pduP=NULL;
Raymond Knopp's avatar
 
Raymond Knopp committed
490
    }
491 492
    
    rn->mch_avtive[subframe]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
493
    break;
494
    
495
  default:
496
    LOG_W(PHY,"[eNB %"PRIu8"] Frame %d subframe %d: unknown relaying type %d \n",
497
	  eNB->Mod_id,proc->frame_tx,subframe,r_type);
498 499 500 501 502
    mch_pduP=NULL;
    break;
  }// switch
  
  if (mch_pduP) {
503
    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0);
504
    // Generate PMCH
505
    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload);
506
  } else {
507
    LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
508
  }
509
  
510
#endif
511
}
512

513
void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
514

515 516
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int **txdataF = eNB->common_vars.txdataF[0];
517
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
518 519
  int subframe = proc->subframe_tx;
  int frame = proc->frame_tx;
520

521
  // generate Cell-Specific Reference Signals for both slots
522
  if (eNB->abstraction_flag==0) {
523 524 525 526 527 528 529 530 531 532 533 534 535 536
    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);
  }    
537

538
  // First half of PSS/SSS (FDD, slot 0)
Raymond Knopp's avatar
 
Raymond Knopp committed
539
  if (subframe == 0) {
540
    if ((fp->frame_type == FDD) &&
541
	(eNB->abstraction_flag==0)) {
542 543 544 545 546 547 548 549 550 551 552
      generate_pss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   0);
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 5 : 4,
		   0);
      
553
    }
554
    
555
    // generate PBCH (Physical Broadcast CHannel) info
556
    if ((frame&3) == 0) {
557
      pbch_pdu[2] = 0;
558
      
559
      // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators
560
      switch (fp->N_RB_DL) {
Raymond Knopp's avatar
 
Raymond Knopp committed
561
      case 6:
562 563
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (0<<5);
	break;
564
	
Raymond Knopp's avatar
 
Raymond Knopp committed
565
      case 15:
566 567 568
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (1<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
569
      case 25:
570 571 572
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
573
      case 50:
574 575 576
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (3<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
577
      case 75:
578 579 580
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (4<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
581
      case 100:
582 583 584
	pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (5<<5);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
585
      default:
586 587 588
	// 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
589
      }
590
      
591
      pbch_pdu[2] = (pbch_pdu[2]&0xef) |
592 593 594
	((fp->phich_config_common.phich_duration << 4)&0x10);
      
      switch (fp->phich_config_common.phich_resource) {
Raymond Knopp's avatar
 
Raymond Knopp committed
595
      case oneSixth:
596 597 598
	pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (0<<2);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
599
      case half:
600 601 602
	pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (1<<2);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
603
      case one:
604 605 606
	pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (2<<2);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
607
      case two:
608 609 610
	pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (3<<2);
	break;
	
Raymond Knopp's avatar
 
Raymond Knopp committed
611
      default:
612 613
	// unreachable
	break;
Raymond Knopp's avatar
 
Raymond Knopp committed
614
      }
615
      
616 617
      pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((frame>>8)&0x3);
      pbch_pdu[1] = frame&0xfc;
618
      pbch_pdu[0] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
619
    }
620 621 622 623
      
    /// First half of SSS (TDD, slot 1)
    
    if ((fp->frame_type == TDD)&&
624
	(eNB->abstraction_flag==0)){
625 626 627 628 629 630
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   1);
    }
631

632
    /// generate PBCH
633
    if (eNB->abstraction_flag==0) {
634
      generate_pbch(&eNB->pbch,
635 636 637 638
                    txdataF,
                    AMP,
                    fp,
                    pbch_pdu,
639
                    frame&3);
640
    }
641 642 643
#ifdef PHY_ABSTRACTION
    else {
      generate_pbch_emul(eNB,pbch_pdu);
644
    }
645
#endif
646

647
  }
648 649
  else if ((subframe == 1) &&
	   (fp->frame_type == TDD)&&
650
	   (eNB->abstraction_flag==0)) {
651 652 653 654 655
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
656
  }
657 658 659 660
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
	   (fp->frame_type == FDD) &&
661
	   (eNB->abstraction_flag==0)) {
662 663 664 665 666 667 668 669 670 671
    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);
672

673
  }
674

675 676 677
  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
	   (fp->frame_type == TDD) &&
678
	   (eNB->abstraction_flag==0)) {
679 680 681 682 683
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
Raymond Knopp's avatar
 
Raymond Knopp committed
684
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
685

686 687 688
  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
	   (fp->frame_type == TDD) &&
689
	   (eNB->abstraction_flag==0)) {
690 691 692 693 694 695
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
696

697
}
Raymond Knopp's avatar
 
Raymond Knopp committed
698

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

701
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
702 703
  int frame = proc->frame_tx;
  int subframe = proc->subframe_tx;
704 705 706 707 708 709 710 711 712

  // 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,
713
				       &eNB->dlsch_SI,
714
				       fp,
715
				       NULL,
716 717 718
				       SI_RNTI,
				       0,
				       P_RNTI,
719 720
				       eNB->UE_stats[0].DL_pmi_single,
				       0);
721 722
    
    
723
    eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE;
724
    
725
    LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
726
	  eNB->dlsch_SI->nCCE[subframe]);
727 728 729 730
    
#if defined(SMBV) 
    
    // configure SI DCI
731 732
    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);
733 734 735 736 737 738 739 740 741 742 743 744 745 746
      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,
747
				       &eNB->dlsch_ra,
748
				       fp,
749
				       NULL,
750 751 752
				       SI_RNTI,
				       dci_alloc->rnti,
				       P_RNTI,
753 754
				       eNB->UE_stats[0].DL_pmi_single,
				       0);
755 756
    
    
757
    eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE;
758
    
759
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
760
	  eNB->dlsch_ra->nCCE[subframe]);
761 762 763
#if defined(SMBV) 
    
    // configure RA DCI
764 765
    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);
766
      smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", dci_alloc, i);
Raymond Knopp's avatar
 
Raymond Knopp committed
767
    }
768 769 770 771 772 773 774 775 776 777
    
#endif
    
  }
  
  else if ((dci_alloc->format != format0)&&
	   (dci_alloc->format != format3)&&
	   (dci_alloc->format != format3A)&&
	   (dci_alloc->format != format4)){ // this is a normal DLSCH allocation
    
Raymond Knopp's avatar
 
Raymond Knopp committed
778

779 780 781 782
    
    if (UE_id>=0) {
#if defined(SMBV) 
      // Configure this user
783 784
      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,
785 786
              dci_alloc->rnti,eNB->transmission_mode[(uint8_t)UE_id]);
	smbv_configure_user(smbv_fname,UE_id+1,eNB->transmission_mode[(uint8_t)UE_id],dci_alloc->rnti);
Raymond Knopp's avatar
 
Raymond Knopp committed
787
      }
788 789
      
#endif
790

791 792 793 794 795 796
      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,
797
					 eNB->dlsch[(uint8_t)UE_id],
798
					 fp,
799
					 &eNB->pdsch_config_dedicated[UE_id],
800 801 802
					 SI_RNTI,
					 0,
					 P_RNTI,
803 804
					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single,
					 eNB->transmission_mode[(uint8_t)UE_id]<7?0:eNB->transmission_mode[(uint8_t)UE_id]);
805
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
806
	    eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
807 808
      
      
Cedric Roux's avatar
Cedric Roux committed
809 810
      T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
        T_INT(dci_alloc->rnti), T_INT(dci_alloc->format),
Cedric Roux's avatar
Cedric Roux committed
811
        T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid),
812 813
        T_INT(eNB->dlsch[(int)UE_id][0]->harq_processes[eNB->dlsch[(int)UE_id][0]->current_harq_pid]->mcs),
        T_INT(eNB->dlsch[(int)UE_id][0]->harq_processes[eNB->dlsch[(int)UE_id][0]->current_harq_pid]->TBS));
814

815
      eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
816
      
Cedric Roux's avatar
Cedric Roux committed
817
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
818
	    dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]);
819 820 821 822
      
#if defined(SMBV) 
      
      // configure UE-spec DCI
823 824
      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);
825
	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
826
      }
827
      
828
#endif
829 830 831
      
      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,
832
	    frame, subframe,UE_id,
833 834
	    dci_alloc->format,
	    1<<dci_alloc->L);
Raymond Knopp's avatar
 
Raymond Knopp committed
835
    } else {
836
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n",
837
	    eNB->Mod_id,frame,dci_alloc->rnti);
838
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
839
  }
840 841
  
}
842

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

845
  int harq_pid;
846
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
847
  int frame = proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
848
  int subframe = proc->subframe_tx;
849
  /*
850 851 852
  uint16_t srsPeriodicity=0;
  uint16_t srsOffset=0;
  uint16_t srsConfigIndex=0;
853
  uint16_t do_srs=0;
854
  */
855
  uint16_t is_srs_pos=0;
856

857
  LOG_D(PHY,
858 859 860
	"[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,
861
			  pdcch_alloc2ul_frame(fp,frame,subframe),
862
			  pdcch_alloc2ul_subframe(fp,subframe)),
863
	frame,
864
	subframe,
865
	pdcch_alloc2ul_frame(fp,frame,subframe),
866 867 868 869 870
	pdcch_alloc2ul_subframe(fp,subframe),
	dci_alloc->rnti,
	dci_alloc->dci_pdu[0],
	1<<dci_alloc->L);
  
871
  is_srs_pos = is_srs_occasion_common(fp,pdcch_alloc2ul_frame(fp,frame,subframe),pdcch_alloc2ul_subframe(fp,subframe));
872
  /*
873 874 875 876
  if (is_srs_pos && eNB->soundingrs_ul_config_dedicated[UE_id].srsConfigDedicatedSetup) {
    srsConfigIndex = eNB->soundingrs_ul_config_dedicated[UE_id].srs_ConfigIndex;
    compute_srs_pos(fp->frame_type, srsConfigIndex, &srsPeriodicity, &srsOffset);
    if ((((10*pdcch_alloc2ul_frame(fp,frame,subframe)+pdcch_alloc2ul_subframe(fp,subframe)) % srsPeriodicity) == srsOffset)) {
877
      do_srs = 1;
878
    }
879
  }
880 881 882
      LOG_D(PHY,"frame %d (%d), subframe %d (%d), UE_id %d: is_srs_pos %d, do_SRS %d, index %d, period %d, offset %d \n",
	    frame,pdcch_alloc2ul_frame(fp,frame,subframe),subframe,pdcch_alloc2ul_subframe(fp,subframe),
	    UE_id,is_srs_pos,do_srs,srsConfigIndex,srsPeriodicity,srsOffset);
883
  */
884

885
  generate_eNB_ulsch_params_from_dci(eNB,
886
				     proc,
887
				     &dci_alloc->dci_pdu[0],
888 889 890 891 892 893 894
				     dci_alloc->rnti,
				     format0,
				     UE_id,
				     SI_RNTI,
				     0,
				     P_RNTI,
				     CBA_RNTI,
895
				     is_srs_pos);  
896 897
  
  LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d\n",
898
	eNB->Mod_id,frame,subframe,dci_alloc->rnti,
899 900 901 902 903
	dci_alloc->firstCCE);
  
#if defined(SMBV) 
  
  // configure UE-spec DCI for UL Grant
904 905
  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);
906
    smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i);
Raymond Knopp's avatar
 
Raymond Knopp committed
907
  }
908 909 910 911 912 913
  
#endif
  
  
  // get the hard_pid for this subframe 
  harq_pid = subframe2harq_pid(fp,
914
			       pdcch_alloc2ul_frame(fp,frame,subframe),
915 916 917
			       pdcch_alloc2ul_subframe(fp,subframe));
  
  if (harq_pid==255) { // should not happen, log an error and exit, this is a fatal error
918
    LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,frame);
919 920 921 922
    mac_xface->macphy_exit("FATAL\n"); 
  }
  
  if ((dci_alloc->rnti  >= CBA_RNTI) && (dci_alloc->rnti < P_RNTI))
923
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1;
924
  else
925
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
926
  
Cedric Roux's avatar
Cedric Roux committed
927
  T(T_ENB_PHY_ULSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
Cedric Roux's avatar
Cedric Roux committed
928 929 930 931 932
    T_INT(dci_alloc->rnti), T_INT(harq_pid),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->mcs),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->round),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->first_rb),
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->nb_rb),
933 934 935
    T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->TBS),
    T_INT(dci_alloc->L),
    T_INT(dci_alloc->firstCCE));
936
}
937

938
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) {
939

940 941
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
942 943 944
  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;
945
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
946
  uint8_t *DLSCH_pdu=NULL;
947
  uint8_t DLSCH_pdu_tmp[input_buffer_length+4]; //[768*8];
948 949
  uint8_t DLSCH_pdu_rar[256];
  int i;
950

951
  LOG_D(PHY,
Cedric Roux's avatar
Cedric Roux committed
952
	"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx64", rv %"PRIu8" (round %"PRIu8")\n",
953
	eNB->Mod_id, dlsch->rnti,harq_pid,
954
	frame, subframe, input_buffer_length,
955 956 957 958 959
	get_G(fp,
	      dlsch_harq->nb_rb,
	      dlsch_harq->rb_alloc,
	      get_Qm(dlsch_harq->mcs),
	      dlsch_harq->Nl,
960 961 962 963
	      num_pdcch_symbols,
	      frame,
	      subframe,
	      dlsch_harq->mimo_mode==TM7?7:0),
964 965 966 967 968
	dlsch_harq->nb_rb,
	dlsch_harq->mcs,
	pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	dlsch_harq->rvidx,
	dlsch_harq->round);
969

970
#if defined(MESSAGE_CHART_GENERATOR_PHY)
971 972 973 974 975 976 977 978 979 980 981
  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,
982 983 984 985
			   num_pdcch_symbols,
			   frame,
			   subframe,
			   dlsch_harq->mimo_mode==TM7?7:0),
986 987 988 989 990 991 992 993 994 995 996 997 998
		     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]++;
999

1000 1001 1002 1003 1004 1005 1006
    if (eNB->mac_enabled==1) {
      if (ra_flag == 0) {
	DLSCH_pdu = mac_xface->get_dlsch_sdu(eNB->Mod_id,
					     eNB->CC_id,
					     frame,
					     dlsch->rnti,
					     0);
Raymond Knopp's avatar
 
Raymond Knopp committed
1007
      }
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
      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;
1023
	    
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
	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;
1034
	      
1035 1036
	  generate_eNB_ulsch_params_from_rar(DLSCH_pdu,
					     frame,
1037
					     subframe,
1038 1039
					     eNB->ulsch[(uint32_t)UE_id],
					     fp);
1040
	      
1041 1042 1043 1044 1045 1046
	  LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n",
		frame,
		subframe,
		UE_id,
		eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
		eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
Cedric Roux's avatar
Cedric Roux committed
1047

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

1057 1058 1059
          mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, (uint16_t)crnti,
                                       eNB->ulsch[UE_id]->Msg3_frame, eNB->ulsch[UE_id]->Msg3_subframe);

Cedric Roux's avatar
Cedric Roux committed
1060 1061 1062
          T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
            T_INT(UE_id), T_INT((uint16_t)crnti), T_INT(1 /* 1 is for initial transmission*/),
            T_INT(eNB->ulsch[UE_id]->Msg3_frame), T_INT(eNB->ulsch[UE_id]->Msg3_subframe));
1063
	}
1064 1065 1066 1067 1068
	if (ue_stats) ue_stats->total_TBS_MAC += dlsch_harq->TBS;
      }
    }
    else {
      DLSCH_pdu = DLSCH_pdu_tmp;
1069
	  
1070 1071 1072
      for (i=0; i<input_buffer_length; i++)
	DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
    }
1073 1074
	
#if defined(SMBV) 
1075

1076 1077 1078 1079 1080
    // 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);
    }
1081

1082
#endif
1083 1084 1085



1086 1087
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1088
    LOG_T(PHY,"eNB DLSCH SDU: \n");
1089

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

1092 1093
    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);
1094

1095

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

1099
    LOG_T(PHY,"\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
1100
#endif
1101
#endif
1102 1103
  } else {
    ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++;
1104 1105
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1106
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
1107 1108
#endif
#endif
1109
  }
1110

1111
  if (eNB->abstraction_flag==0) {
1112

1113 1114 1115
    LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag);
    // 36-212
    start_meas(&eNB->dlsch_encoding_stats);
1116 1117 1118 1119 1120 1121 1122 1123
    eNB->te(eNB,
	    DLSCH_pdu,
	    num_pdcch_symbols,
	    dlsch,
	    frame,subframe,
	    &eNB->dlsch_rate_matching_stats,
	    &eNB->dlsch_turbo_encoding_stats,
	    &eNB->dlsch_interleaving_stats);
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
    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,
1135 1136 1137
			   num_pdcch_symbols,
			   frame,subframe,
			   0),
1138 1139 1140
		     0,
		     subframe<<1);
    stop_meas(&eNB->dlsch_scrambling_stats);
1141

1142 1143 1144
    start_meas(&eNB->dlsch_modulation_stats);


1145 1146
    dlsch_modulation(eNB,
		     eNB->common_vars.txdataF[0],
1147 1148 1149 1150 1151
		     AMP,
		     subframe,
		     num_pdcch_symbols,
		     dlsch,
		     dlsch1);
1152
	
1153 1154
    stop_meas(&eNB->dlsch_modulation_stats);
  }
1155 1156


1157
#ifdef PHY_ABSTRACTION
1158 1159 1160 1161 1162 1163 1164
  else {
    start_meas(&eNB->dlsch_encoding_stats);
    dlsch_encoding_emul(eNB,
			DLSCH_pdu,
			dlsch);
    stop_meas(&eNB->dlsch_encoding_stats);
  }
1165

Raymond Knopp's avatar
 
Raymond Knopp committed
1166
#endif
1167
  dlsch->active = 0;
1168
}
1169

1170
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
1171
			   eNB_rxtx_proc_t *proc,
1172
                           relaying_type_t r_type,
1173
			   PHY_VARS_RN *rn,
1174 1175
			   int do_meas,
			   int do_pdcch_flag)
1176 1177
{
  UNUSED(rn);
1178 1179
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
1180
  //  uint16_t input_buffer_length;
1181
  uint32_t i,j,aa;
1182 1183 1184
  uint8_t harq_pid;
  DCI_PDU *DCI_pdu;
  DCI_PDU DCI_pdu_tmp;
1185
  int8_t UE_id=0;
1186 1187 1188
  uint8_t num_pdcch_symbols=0;
  uint8_t ul_subframe;
  uint32_t ul_frame;
1189
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1190
  DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL;
1191

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

1194 1195 1196
#if defined(SMBV) 
  // counts number of allocations in subframe
  // there is at least one allocation for PDCCH
1197
  uint8_t smbv_alloc_cnt = 1;Exiting eNB thread RXn_TXnp4
1198

1199
#endif
1200

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

1203
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
1204
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
1205

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

1208 1209
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    // If we've dropped the UE, go back to PRACH mode for this UE
1210 1211 1212
    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);
1213
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1214
    }
1215
    if (eNB->UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) {
1216
      LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n",
1217 1218
            eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->UE_stats[i].ulsch_consecutive_errors);
      eNB->UE_stats[i].ulsch_consecutive_errors=0;
1219 1220 1221
      mac_xface->UL_failure_indication(eNB->Mod_id,
				       eNB->CC_id,
				       frame,
1222
				       eNB->UE_stats[i].crnti,
1223 1224
				       subframe);
				       
Raymond Knopp's avatar
 
Raymond Knopp committed
1225
    }
1226
	
1227

Raymond Knopp's avatar
 
Raymond Knopp committed
1228
  }
1229 1230 1231


  // Get scheduling info for next subframe
1232
  // This is called only for the CC_id = 0 and triggers scheduling for all CC_id's
1233 1234
  if (eNB->mac_enabled==1) {
    if (eNB->CC_id == 0) {
1235
      mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,frame,subframe);//,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1236
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1237
  }
1238

1239
  // clear the transmit data array for the current subframe
1240
  if (eNB->abstraction_flag==0) {
1241
    for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {      
1242
      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
1243
             0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
Raymond Knopp's avatar
 
Raymond Knopp committed
1244
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1245
  }
1246

1247
  if (is_pmch_subframe(frame,subframe,fp)) {
1248
    pmch_procedures(eNB,proc,rn,r_type);
1249 1250 1251
  }
  else {
    // this is not a pmch subframe, so generate PSS/SSS/PBCH
1252
    common_signal_procedures(eNB,proc);
1253
  }
1254

1255
#if defined(SMBV) 
1256

Raymond Knopp's avatar
 
Raymond Knopp committed
1257
  // PBCH takes one allocation
1258
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
1259
    if (subframe==0)
Raymond Knopp's avatar
 
Raymond Knopp committed
1260 1261
      smbv_alloc_cnt++;
  }
1262

1263
#endif
1264

1265
  if (eNB->mac_enabled==1) {
1266 1267
    // Parse DCI received from MAC
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
1268 1269
    DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
				     eNB->CC_id,
1270
				     frame,
1271 1272 1273 1274
				     subframe);
  }
  else {
    DCI_pdu = &DCI_pdu_tmp;
1275
#ifdef EMOS_CHANNEL
1276
    fill_dci_emos(DCI_pdu,eNB);
1277
#else
1278
    fill_dci(DCI_pdu,eNB,proc);
1279 1280 1281 1282 1283 1284 1285 1286
    // clear previous allocation information for all UEs
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
      if (eNB->dlsch[i][0]){
        for (j=0; j<8; j++)
          eNB->dlsch[i][0]->harq_processes[j]->round = 0;
      }
    }

1287
#endif
1288
  }
1289

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

1294 1295 1296
  if ((subframe_select(fp,ul_subframe)==SF_UL) ||
      (fp->frame_type == FDD)) {
    harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
1297

1298
    // clear DCI allocation maps for new subframe
1299
    for (i=0; i<NUMBER_OF_UE_MAX; i++)
1300 1301 1302
      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
1303 1304
      }
  }
1305

Raymond Knopp's avatar
 
Raymond Knopp committed
1306
  // clear previous allocation information for all UEs
1307
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
1308 1309
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1310
  }
1311

1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
  /* save old HARQ information needed for PHICH generation */
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    if (eNB->ulsch[i]) {
      /* Store first_rb and n_DMRS for correct PHICH generation below.
       * For PHICH generation we need "old" values of last scheduling
       * for this HARQ process. 'generate_eNB_dlsch_params' below will
       * overwrite first_rb and n_DMRS and 'generate_phich_top', done
       * after 'generate_eNB_dlsch_params', would use the "new" values
       * instead of the "old" ones.
       *
       * This has been tested for FDD only, may be wrong for TDD.
       *
       * TODO: maybe we should restructure the code to be sure it
       *       is done correctly. The main concern is if the code
       *       changes and first_rb and n_DMRS are modified before
       *       we reach here, then the PHICH processing will be wrong,
       *       using wrong first_rb and n_DMRS values to compute
       *       ngroup_PHICH and nseq_PHICH.
       *
       * TODO: check if that works with TDD.
       */
      if ((subframe_select(fp,ul_subframe)==SF_UL) ||
          (fp->frame_type == FDD)) {
        harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
        eNB->ulsch[i]->harq_processes[harq_pid]->previous_first_rb =
            eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
        eNB->ulsch[i]->harq_processes[harq_pid]->previous_n_DMRS =
            eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS;
      }
    }
  }

1344

1345
  // loop over all DCIs for this subframe to generate DLSCH allocations
1346 1347
  for (i=0; i<DCI_pdu->Num_dci; i++) {
    LOG_D(PHY,"[eNB] Subframe %d: DCI %d/%d : rnti %x, CCEind %d\n",subframe,i,DCI_pdu->Num_dci,DCI_pdu->dci_alloc[i].rnti,DCI_pdu->dci_alloc[i].firstCCE);
1348 1349 1350
    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);
1351
    dci_alloc = &DCI_pdu->dci_alloc[i];
1352

1353 1354 1355 1356
    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);
1357 1358
      else
	UE_id = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1359
    }
1360 1361
    else UE_id=0;
    
1362
    generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
1363

Raymond Knopp's avatar
 
Raymond Knopp committed
1364
  }
1365

1366 1367
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

Raymond Knopp's avatar
 
Raymond Knopp committed
1368
  // Apply physicalConfigDedicated if needed
1369 1370
  // 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);
1371

1372
  // Now loop again over the DCIs for UL configuration
1373
  for (i=0; i<DCI_pdu->Num_dci; i++) {
Cedric Roux's avatar
Cedric Roux committed
1374
    dci_alloc = &DCI_pdu->dci_alloc[i];
Raymond Knopp's avatar
 
Raymond Knopp committed
1375

1376 1377 1378
    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);
1379 1380
      else
	UE_id = i;
1381
      
1382
      if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
1383
	LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
1384
	mac_xface->macphy_exit("FATAL\n"); 
1385
      }
1386
      generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1387
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1388
  }
1389

1390 1391


Lionel Gauthier's avatar
Lionel Gauthier committed
1392 1393


Raymond Knopp's avatar
 
Raymond Knopp committed
1394
  // if we have DCI to generate do it now
1395
  if (DCI_pdu->Num_dci>0) {
Lionel Gauthier's avatar
Lionel Gauthier committed
1396

1397 1398

  } else { // for emulation!!
1399 1400
    eNB->num_ue_spec_dci[(subframe)&1]=0;
    eNB->num_common_dci[(subframe)&1]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1401
  }
1402

1403

1404
  if (eNB->abstraction_flag == 0) {
1405
    if (do_pdcch_flag) {
1406 1407 1408
      if (DCI_pdu->Num_dci > 0) {
	LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (Num_dci=%d)\n",eNB->Mod_id,frame, subframe,
	      DCI_pdu->Num_dci);
1409
      }
1410

1411
      num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_dci,
1412 1413 1414 1415 1416 1417 1418 1419 1420
					   DCI_pdu->dci_alloc,
					   0,
					   AMP,
					   fp,
					   eNB->common_vars.txdataF[0],
					   subframe);
    }
    else {
      num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
1421 1422
      LOG_D(PHY,"num_pdcch_symbols %"PRIu8" (Num_dci %d)\n",num_pdcch_symbols,
	    DCI_pdu->Num_dci);
1423
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1424
  }
1425

1426
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
Raymond Knopp's avatar
 
Raymond Knopp committed
1427
  else {
1428
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
1429
    num_pdcch_symbols = generate_dci_top_emul(eNB,DCI_pdu->Num_dci,DCI_pdu->dci_alloc,subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
1430
  }
1431

1432 1433
#endif

1434 1435
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);

1436
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
1437

1438 1439
#if defined(SMBV) 
  // Sets up PDCCH and DCI table
1440 1441
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4) && (DCI_pdu->Num_dci>0)) {
    LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",frame,subframe,DCI_pdu->Num_dci);
1442
    dump_dci(fp,&DCI_pdu->dci_alloc[0]);
1443
    smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_dci);
1444 1445 1446
  }
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1447
  // Check for SI activity
1448

1449
  if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
1450

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

1453
#if defined(SMBV) 
1454

Raymond Knopp's avatar
 
Raymond Knopp committed
1455
    // Configures the data source of allocation (allocation is configured by DCI)
1456 1457
    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
1458 1459
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
    }
1460 1461

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1462
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1463

Raymond Knopp's avatar
 
Raymond Knopp committed
1464
  // Check for RA activity
1465
  if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
1466

1467
#if defined(SMBV) 
1468

1469
    // Configures the data source of allocation (allocation is configured by DCI)
1470 1471
    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);
1472 1473 1474
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length);
    }
    
1475
#endif
1476 1477
    
    
1478
    LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA),Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n",
1479
	  eNB->Mod_id,
1480
	  frame, subframe,
1481 1482
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
1483
    
1484
    pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols);
1485 1486
    
    
1487
    eNB->dlsch_ra->active = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1488
  }
1489

Raymond Knopp's avatar
 
Raymond Knopp committed
1490
  // Now scan UE specific DLSCH
1491
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
1492 1493 1494 1495
    {
      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)) {
1496

1497
	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);
1498 1499


Raymond Knopp's avatar
 
Raymond Knopp committed
1500
      }
1501

1502 1503 1504
      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)) {
1505

1506 1507
	// 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
1508
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1509
    }
1510

1511 1512


Raymond Knopp's avatar
 
Raymond Knopp committed
1513
  // if we have PHICH to generate
1514

1515
  if (is_phich_subframe(fp,subframe))
1516 1517 1518 1519
    {
      generate_phich_top(eNB,
			 proc,
			 AMP,
1520
			 0);
1521
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1522

1523 1524 1525 1526 1527 1528 1529
  /*
  if (frame>=10 && subframe>=9) {
    write_output("/tmp/txsigF0.m","txsF0", &eNB->common_vars.txdataF[0][0][0],120*eNB->frame_parms.ofdm_symbol_size,1,1);
    write_output("/tmp/txsigF1.m","txsF1", &eNB->common_vars.txdataF[0][0][0],120*eNB->frame_parms.ofdm_symbol_size,1,1);
    abort();
  }
  */
1530

1531
#ifdef EMOS
1532
  phy_procedures_emos_eNB_TX(subframe, eNB);
Raymond Knopp's avatar
 
Raymond Knopp committed
1533
#endif
1534

1535
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
1536
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
1537
  
1538 1539
}

1540
void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid)
1541
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1542
  // this prepares the demodulation of the first PUSCH of a new user, containing Msg3
1543 1544
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1545

Raymond Knopp's avatar
 
Raymond Knopp committed
1546
  LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
1547
        eNB->Mod_id,
1548
        frame,subframe,
1549 1550 1551 1552
        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;
1553

1554 1555 1556
  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))   {
1557

1558
    //    harq_pid = 0;
1559

1560 1561 1562
    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
1563
    LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
1564
          eNB->Mod_id,
1565
          frame,subframe,UE_id);
1566 1567 1568 1569 1570 1571 1572 1573 1574
  }
}


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

1575
void process_HARQ_feedback(uint8_t UE_id,
1576
                           PHY_VARS_eNB *eNB,
1577
			   eNB_rxtx_proc_t *proc,
1578 1579 1580 1581 1582
                           uint8_t pusch_flag,
                           uint8_t *pucch_payload,
                           uint8_t pucch_sel,
                           uint8_t SR_payload)
{
1583

1584
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1585
  uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe;
1586 1587
  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];
1588
  LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
1589
  uint8_t subframe_m4,M,m;
1590 1591
  int mp;
  int all_ACKed=1,nb_alloc=0,nb_ACK=0;
1592 1593
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1594
  int harq_pid = subframe2harq_pid( fp,frame,subframe);
1595

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

1599 1600
    dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
    M=1;
1601

1602
    if (pusch_flag == 1) {
1603
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1604
      if (dlsch->subframe_tx[subframe_m4]==1)
1605 1606
	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);
1607 1608
    }
    else {
1609
      dlsch_ACK[0] = pucch_payload[0];
1610
      LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",eNB->Mod_id,
1611
	    frame,dlsch_ACK[0],subframe_m4);
kaltenbe's avatar
kaltenbe committed
1612
      /*
1613
	if (dlsch_ACK[0]==0)
1614
	AssertFatal(0,"Exiting on NAK on PUCCH\n");
kaltenbe's avatar
kaltenbe committed
1615
      */
1616
    }
1617

Lionel Gauthier's avatar
Lionel Gauthier committed
1618 1619 1620

#if defined(MESSAGE_CHART_GENERATOR_PHY)
    MSC_LOG_RX_MESSAGE(
1621 1622 1623 1624 1625 1626 1627 1628 1629 1630
		       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
1631
#endif
1632 1633
  } else { // TDD Handle M=1,2 cases only

1634
    M=ul_ACK_subframe2_M(fp,
1635 1636
                         subframe);

1637 1638 1639 1640 1641 1642 1643 1644
    // 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

1645
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1646
      dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling)
1647
	?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];
1648
    }
1649

1650
    else {  // PUCCH ACK/NAK
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
      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;
        }
1686
      }
1687
    }
1688 1689 1690 1691
  }

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

    for (m=0; m<M; m++) {
1695
      dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1696 1697
						 subframe,
						 m);
1698 1699 1700

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

1703 1704
    if (nb_alloc == nb_ACK)
      all_ACKed = 1;
1705
    else
1706
      all_ACKed = 0;
1707 1708 1709
  }


1710
  for (m=0,mp=-1; m<M; m++) {
1711

1712
    dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1713 1714
					       subframe,
					       m);
1715

1716 1717
    if (dlsch->subframe_tx[dl_subframe]==1) {
      if (pusch_flag == 1)
1718
        mp++;
1719
      else
1720
        mp = m;
1721

1722
      dl_harq_pid[m]     = dlsch->harq_ids[dl_subframe];
1723
      harq_pid_updated[UE_id][dl_harq_pid[m]] = 1;
1724

1725
      if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
1726 1727 1728 1729
        if ((SR_payload == 1)&&(all_ACKed == 1))
          dlsch_ACK[m] = 1;
        else
          dlsch_ACK[m] = 0;
1730
      }
1731

1732
      if (dl_harq_pid[m]<dlsch->Mdlharq) {
1733 1734
        dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
1735
        LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id,
1736 1737 1738 1739 1740 1741 1742 1743 1744
              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");

1745
#endif
1746 1747 1748 1749 1750 1751 1752 1753

        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
1754
            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,
1755
                  dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
1756
#endif
1757

1758
            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),
1759
              T_INT(dl_harq_pid[m]));
1760

1761 1762 1763 1764 1765 1766 1767 1768 1769
            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++;

1770

1771
            if (dlsch_harq_proc->round == dlsch->Mlimit) {
1772 1773
              // This was the last round for DLSCH so reset round and increment l2_error counter
#ifdef DEBUG_PHY_PROC
1774
              LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",eNB->Mod_id,
1775
                    dlsch->rnti,dl_harq_pid[m]);
1776
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1777
#if defined(MESSAGE_CHART_GENERATOR_PHY)
1778
              MSC_LOG_EVENT(MSC_PHY_ENB, "0 HARQ DLSCH Failed RNTI %"PRIx16" round %u",
1779 1780
                            dlsch->rnti,
                            dlsch_harq_proc->round);
Lionel Gauthier's avatar
Lionel Gauthier committed
1781
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1782

1783 1784 1785 1786 1787 1788 1789
              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
1790
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
1791
                  dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
1792
#endif
1793

1794
            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),
1795
              T_INT(dl_harq_pid[m]));
1796

1797 1798 1799 1800 1801 1802 1803 1804
            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 +
1805
	      eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1806 1807
            /*
              ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
1808
              eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1809 1810
            */
          }
1811
	 
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
          // 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);
1823
#endif
1824
	  harq_pid_round[UE_id][dl_harq_pid[m]] = dlsch_harq_proc->round;
1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843
          // 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;
          }
        }
1844
      }
1845
    }
1846 1847 1848
  }
}

1849
void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
1850
		      eNB_rxtx_proc_t *proc,
1851 1852 1853 1854 1855 1856
                      uint8_t UE_id,
                      int16_t *n1_pucch0,
                      int16_t *n1_pucch1,
                      int16_t *n1_pucch2,
                      int16_t *n1_pucch3)
{
1857

1858
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
1859
  uint8_t nCCE0,nCCE1;
1860
  int sf;
1861 1862
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1863 1864

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

1867 1868
    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];
1869
      *n1_pucch1 = -1;
1870
    } else {
1871 1872 1873
      *n1_pucch0 = -1;
      *n1_pucch1 = -1;
    }
1874
  } else {
1875

1876 1877 1878
    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
1879
        /*  if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
1880 1881 1882 1883 1884
	    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;*/
1885

1886 1887
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1888 1889 1890 1891 1892 1893 1894
          *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

1895 1896
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1897 1898 1899 1900 1901 1902 1903 1904 1905
          *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;
1906 1907
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1908 1909 1910 1911 1912 1913 1914
          *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;
1915 1916
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4];
1917 1918 1919 1920 1921 1922 1923
          *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",
1924
              eNB->Mod_id,
1925 1926 1927
              frame,
              subframe,frame_parms->tdd_config);
        return;
1928
      }
1929

1930
      break;
1931

1932 1933
    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)
1934 1935
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
1936 1937 1938 1939
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1940 1941
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1942 1943 1944 1945 1946
          *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",
1947
              eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7],eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]);
1948

1949 1950
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[8];
1951 1952 1953 1954 1955
          *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;

1956 1957
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7];
1958 1959 1960 1961 1962
          *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
1963 1964
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1965 1966 1967 1968
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1969 1970
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1971 1972 1973 1974 1975
          *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",
1976
              eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
1977
        return;
1978
      }
1979

1980
      break;
1981 1982
    }  // switch tdd_config

1983 1984 1985
    // Don't handle the case M>2
    *n1_pucch2 = -1;
    *n1_pucch3 = -1;
1986 1987 1988
  }
}

1989
void prach_procedures(PHY_VARS_eNB *eNB) {
1990

1991
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1992 1993 1994 1995
  uint16_t preamble_energy_list[64],preamble_delay_list[64];
  uint16_t preamble_max,preamble_energy_max;
  uint16_t i;
  int8_t UE_id;
1996 1997
  int subframe = eNB->proc.subframe_prach;
  int frame = eNB->proc.frame_prach;
1998
  uint8_t CC_id = eNB->CC_id;
lfarizav's avatar
lfarizav committed
1999
  int do_ofdm_mod = PHY_vars_UE_g[0][0]->do_ofdm_mod;
2000

2001
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
2002 2003
  memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
  memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
2004

2005
  if (eNB->abstraction_flag == 0) {
lfarizav's avatar
lfarizav committed
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
    if (do_ofdm_mod)
    {
    	LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id, 
          frame,subframe,dB_fixed(signal_energy(&eNB->common_vars.rxdataF[0][0][subframe*fp->symbols_per_tti*fp->ofdm_symbol_size],512)) - eNB->rx_total_gain_dB);
	rx_prach_freq(eNB,
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
    }
    else
    {
    	LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id, 
2019
          frame,subframe,dB_fixed(signal_energy(&eNB->common_vars.rxdata[0][0][subframe*fp->samples_per_tti],512)) - eNB->rx_total_gain_dB);
2020

lfarizav's avatar
lfarizav committed
2021
    	rx_prach(eNB,
2022 2023 2024 2025
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
lfarizav's avatar
lfarizav committed
2026 2027
	  	printf("[prach] ook\n");
      write_output("prach_rxF_comp1.m","prach_rxF_comp1",eNB->prach_vars.prachF,1024,1,1);
lfarizav's avatar
lfarizav committed
2028
    }
2029 2030 2031
  } else {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {

2032
      LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
2033
            UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
2034
            PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
2035
            fp->prach_config_common.rootSequenceIndex,
2036 2037
            PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex);

Raymond Knopp's avatar
 
Raymond Knopp committed
2038
      if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) &&
2039
          (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex ==
2040
           fp->prach_config_common.rootSequenceIndex) ) {
2041 2042 2043
        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;

2044
      }
2045
    }
2046
  }
2047

2048 2049 2050
  preamble_energy_max = preamble_energy_list[0];
  preamble_max = 0;

2051
  for (i=1; i<64; i++) {
2052 2053 2054 2055
    if (preamble_energy_max < preamble_energy_list[i]) {
      preamble_energy_max = preamble_energy_list[i];
      preamble_max = i;
    }
2056 2057 2058
  }

#ifdef DEBUG_PHY_PROC
2059
  LOG_D(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
2060 2061 2062
        preamble_max,
        preamble_energy_list[preamble_max],
        preamble_delay_list[preamble_max]);
2063 2064
#endif

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

2067
    UE_id = find_next_ue_index(eNB);
2068
 
2069
    if (UE_id>=0) {
2070
      eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
2071

2072
      eNB->UE_stats[(uint32_t)UE_id].sector = 0;
2073
      LOG_D(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure (UE_id %d) with preamble %d, energy %d.%d dB, delay %d\n",
2074 2075
            eNB->Mod_id,
            eNB->CC_id,
2076 2077
            frame,
            subframe,
2078
	    UE_id,
2079 2080 2081 2082
            preamble_max,
            preamble_energy_max/10,
            preamble_energy_max%10,
            preamble_delay_list[preamble_max]);
2083

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

2087
      if (eNB->mac_enabled==1) {
2088 2089
        uint8_t update_TA  = 4;
	uint8_t update_TA2 = 1;
2090
        switch (fp->N_RB_DL) {
2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102
        case 6:
          update_TA = 16;
          break;

        case 25:
          update_TA = 4;
          break;

        case 50:
          update_TA = 2;
          break;

2103 2104 2105
	case 75:
	  update_TA  = 3;
	  update_TA2 = 2;
2106
        case 100:
2107
          update_TA  = 1;
2108 2109 2110
          break;
        }

2111 2112 2113 2114
	mac_xface->initiate_ra_proc(eNB->Mod_id,
				    eNB->CC_id,
				    frame,
				    preamble_max,
2115
				    preamble_delay_list[preamble_max]*update_TA/update_TA2,
2116
				    0,subframe,0);
2117 2118
      }      

2119
    } else {
2120
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many");
2121
      LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
2122
            eNB->Mod_id,frame, subframe);
2123
    }
2124
  }
2125
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
2126 2127
}

2128
void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,uint8_t do_srs)
Cedric Roux's avatar
Cedric Roux committed
2129
{
2130
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2131
  uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0};
Cedric Roux's avatar
Cedric Roux committed
2132
  int16_t n1_pucch0 = -1, n1_pucch1 = -1, n1_pucch2 = -1, n1_pucch3 = -1;
2133 2134
  uint8_t do_SR = 0;
  uint8_t pucch_sel = 0;
2135
  int32_t metric0=0,metric1=0,metric0_SR=0;
2136 2137
  ANFBmode_t bundling_flag;
  PUCCH_FMT_t format;
2138 2139
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2140

2141 2142
  if ((eNB->dlsch[UE_id][0]) &&
      (eNB->dlsch[UE_id][0]->rnti>0) &&
Cedric Roux's avatar
Cedric Roux committed
2143
      (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) {
2144

2145
    // check SR availability
2146 2147
    do_SR = is_SR_subframe(eNB,proc,UE_id);
    //      do_SR = 0;
Cedric Roux's avatar
Cedric Roux committed
2148

2149 2150
    // Now ACK/NAK
    // First check subframe_tx flag for earlier subframes
2151

2152
    get_n1_pucch_eNB(eNB,
Cedric Roux's avatar
Cedric Roux committed
2153 2154 2155 2156 2157 2158 2159
                     proc,
                     UE_id,
                     &n1_pucch0,
                     &n1_pucch1,
                     &n1_pucch2,
                     &n1_pucch3);

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

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

2169 2170 2171
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
Cedric Roux's avatar
Cedric Roux committed
2172 2173
        eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
        break;
2174
      case 15:
Cedric Roux's avatar
Cedric Roux committed
2175 2176
        eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
        break;
2177
      case 25:
Cedric Roux's avatar
Cedric Roux committed
2178 2179
        eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
        break;
2180
      case 50:
Cedric Roux's avatar
Cedric Roux committed
2181 2182 2183
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
        break;
2184
      case 75:
Cedric Roux's avatar
Cedric Roux committed
2185 2186 2187
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
        break;
2188
      case 100:
Cedric Roux's avatar
Cedric Roux committed
2189 2190 2191
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
        break;
2192
      default:
Cedric Roux's avatar
Cedric Roux committed
2193 2194
        LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
        break;
2195
      }
2196

2197
      if (do_SR == 1) {
Cedric Roux's avatar
Cedric Roux committed
2198 2199 2200 2201 2202 2203 2204 2205 2206
        eNB->UE_stats[UE_id].sr_total++;


        if (eNB->abstraction_flag == 0) {
          metric0_SR = rx_pucch(eNB,
                                pucch_format1,
                                UE_id,
                                eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
                                0, // n2_pucch
2207
                                do_srs, // shortened format
Cedric Roux's avatar
Cedric Roux committed
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219
                                &SR_payload,
                                frame,
                                subframe,
                                PUCCH1_THRES);
          LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (SR n1pucch is %d)\n",
                eNB->Mod_id,
                eNB->ulsch[UE_id]->rnti,
                frame,
                subframe,
                SR_payload,
                eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex);
        }
2220
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
        else {
          metric0_SR = rx_pucch_emul(eNB,
                                     proc,
                                     UE_id,
                                     pucch_format1,
                                     0,
                                     &SR_payload);
          LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",eNB->Mod_id,
                eNB->ulsch[UE_id]->rnti,frame,subframe,SR_payload,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex);
        }
2231
#endif
2232
      }// do_SR==1
Cedric Roux's avatar
Cedric Roux committed
2233

2234
      if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR
Cedric Roux's avatar
Cedric Roux committed
2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246
      } else if (fp->frame_type==FDD) { // FDD
        // if SR was detected, use the n1_pucch from SR, else use n1_pucch0
        //          n1_pucch0 = (SR_payload==1) ? eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex:n1_pucch0;

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

        if (eNB->abstraction_flag == 0) {
          metric0 = rx_pucch(eNB,
                             pucch_format1a,
                             UE_id,
                             (uint16_t)n1_pucch0,
                             0, //n2_pucch
2247
                             do_srs, // shortened format
Cedric Roux's avatar
Cedric Roux committed
2248 2249 2250 2251 2252
                             pucch_payload0,
                             frame,
                             subframe,
                             PUCCH1a_THRES);
        }
2253
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2254 2255 2256 2257 2258 2259 2260 2261
        else {
          metric0 = rx_pucch_emul(eNB,
                                  proc,
                                  UE_id,
                                  pucch_format1a,
                                  0,
                                  pucch_payload0);
        }
2262
#endif
Cedric Roux's avatar
Cedric Roux committed
2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276

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

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

          if (eNB->abstraction_flag == 0) {
            metric0=rx_pucch(eNB,
                             pucch_format1a,
                             UE_id,
                             eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
                             0, //n2_pucch
2277
                             do_srs, // shortened format
Cedric Roux's avatar
Cedric Roux committed
2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294
                             pucch_payload0,
                             frame,
                             subframe,
                             PUCCH1a_THRES);
          }
#ifdef PHY_ABSTRACTION
          else {
            metric0 = rx_pucch_emul(eNB,
                                    proc,
                                    UE_id,
                                    pucch_format1a,
                                    0,
                                    pucch_payload0);
          }
#endif
        }

2295
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2296 2297 2298 2299 2300
        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);
2301
#endif
2302

Cedric Roux's avatar
Cedric Roux committed
2303 2304 2305 2306 2307 2308 2309
        process_HARQ_feedback(UE_id,eNB,proc,
                            0,// pusch_flag
                            pucch_payload0,
                            2,
                            SR_payload);
      } // FDD
      else {  //TDD
2310

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

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

Cedric Roux's avatar
Cedric Roux committed
2315 2316
        if ((fp->frame_type==FDD) ||
          (bundling_flag==bundling)    ||
gabrielC's avatar
gabrielC committed
2317
          ((fp->frame_type==TDD)&&(fp->tdd_config==1)&&((subframe!=2)&&(subframe!=7)))) {
Cedric Roux's avatar
Cedric Roux committed
2318 2319 2320 2321
          format = pucch_format1a;
        } else {
          format = pucch_format1b;
        }
2322

Cedric Roux's avatar
Cedric Roux committed
2323 2324
        // if SR was detected, use the n1_pucch from SR
        if (SR_payload==1) {
2325
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2326 2327 2328 2329
          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);
2330
#endif
2331

Cedric Roux's avatar
Cedric Roux committed
2332 2333 2334 2335 2336 2337
          if (eNB->abstraction_flag == 0)
            metric0 = rx_pucch(eNB,
                               format,
                               UE_id,
                               eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
                               0, //n2_pucch
2338
                               do_srs, // shortened format
Cedric Roux's avatar
Cedric Roux committed
2339 2340 2341 2342 2343
                               pucch_payload0,
                               frame,
                               subframe,
                               PUCCH1a_THRES);
          else {
2344
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2345 2346 2347 2348 2349
            metric0 = rx_pucch_emul(eNB,proc,
                                    UE_id,
                                    format,
                                    0,
                                    pucch_payload0);
2350
#endif
Cedric Roux's avatar
Cedric Roux committed
2351 2352
          }
        } else { //using n1_pucch0/n1_pucch1 resources
2353
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2354 2355 2356 2357
          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);
2358
#endif
Cedric Roux's avatar
Cedric Roux committed
2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369
          metric0=0;
          metric1=0;

          // Check n1_pucch0 metric
          if (n1_pucch0 != -1) {
            if (eNB->abstraction_flag == 0)
              metric0 = rx_pucch(eNB,
                                 format,
                                 UE_id,
                                 (uint16_t)n1_pucch0,
                                 0, // n2_pucch
2370
				 do_srs, // shortened format
Cedric Roux's avatar
Cedric Roux committed
2371 2372 2373 2374 2375
                                 pucch_payload0,
                                 frame,
                                 subframe,
                                 PUCCH1a_THRES);
            else {
2376
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2377 2378 2379 2380 2381 2382
              metric0 = rx_pucch_emul(eNB,
                                      proc,
                                      UE_id,
                                      format,
                                      0,
                                      pucch_payload0);
2383
#endif
Cedric Roux's avatar
Cedric Roux committed
2384 2385
            }
          }
2386

Cedric Roux's avatar
Cedric Roux committed
2387 2388 2389 2390 2391 2392 2393 2394
          // Check n1_pucch1 metric
          if (n1_pucch1 != -1) {
            if (eNB->abstraction_flag == 0)
              metric1 = rx_pucch(eNB,
                                 format,
                                 UE_id,
                                 (uint16_t)n1_pucch1,
                                 0, //n2_pucch
2395
                                 do_srs, // shortened format
Cedric Roux's avatar
Cedric Roux committed
2396 2397 2398 2399 2400
                                 pucch_payload1,
                                 frame,
                                 subframe,
                                 PUCCH1a_THRES);
            else {
2401
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2402 2403 2404 2405 2406 2407
              metric1 = rx_pucch_emul(eNB,
                                      proc,
                                      UE_id,
                                      format,
                                      1,
                                      pucch_payload1);
2408
#endif
Cedric Roux's avatar
Cedric Roux committed
2409 2410 2411
            }
          }
        }
2412

Cedric Roux's avatar
Cedric Roux committed
2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428
        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
        }
2429

2430
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2431 2432 2433 2434
        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]);
2435
#endif
Cedric Roux's avatar
Cedric Roux committed
2436 2437 2438 2439 2440 2441
        process_HARQ_feedback(UE_id,eNB,proc,
                              0,// pusch_flag
                              pucch_payload,
                              pucch_sel,
                              SR_payload);
      } // TDD
2442
    }
Cedric Roux's avatar
Cedric Roux committed
2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465

    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);
      }
    }
  }
2466
}
2467

2468

2469
void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
2470

2471 2472
  uint8_t access_mode;
  int num_active_cba_groups;
2473 2474
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2475 2476
  uint16_t rnti=0;
  int ret=0;
2477
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2478

2479 2480
  if (eNB->ulsch[UE_id]==NULL) return;

2481
  num_active_cba_groups = eNB->ulsch[UE_id]->num_active_cba_groups;
2482 2483
 
  if ((num_active_cba_groups > 0) &&
2484 2485
      (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)) {
2486 2487 2488 2489
    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",
2490
	  eNB->Mod_id,harq_pid,
2491
	  frame,subframe,
2492
	  UE_id, (uint16_t)eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->UE_stats[UE_id].mode]);
2493
#endif
2494
    
2495
    if (eNB->abstraction_flag==0) {
2496
      rx_ulsch(eNB,proc,
2497
	       eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2498
	       UE_id,
2499
	       eNB->ulsch,
2500 2501 2502 2503 2504
	       0);
    }
    
#ifdef PHY_ABSTRACTION
    else {
2505
      rx_ulsch_emul(eNB,proc,
2506
		    eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2507
		    UE_id);
2508 2509
    }
    
2510
#endif
2511
    
2512
    if (eNB->abstraction_flag == 0) {
2513
      ret = ulsch_decoding(eNB,proc,
2514 2515
			   UE_id,
			   0, // control_only_flag
2516 2517
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->V_UL_DAI,
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2518 2519 2520 2521
    }
    
#ifdef PHY_ABSTRACTION
    else {
2522
      ret = ulsch_decoding_emul(eNB,
2523
				proc,
2524 2525 2526 2527 2528 2529
				UE_id,
				&rnti);
    }
    
#endif
    
2530
    if (eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2531
#ifdef DEBUG_PHY_PROC
2532
      
2533
      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);
2534 2535
#endif
      access_mode = UNKNOWN_ACCESS;
2536 2537 2538
      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],
2539
		  fp->N_RB_DL,
2540
		  &rnti, &access_mode);
2541
      eNB->UE_stats[UE_id].rank = eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_RI[0];
2542 2543
    }
    
2544 2545
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0;
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE;
2546
      
2547 2548 2549 2550
    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)) {
2551
#ifdef DEBUG_PHY_PROC
2552 2553 2554
      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);
2555
#endif
2556 2557 2558 2559
      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;
    }
2560

2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575
    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;
2576 2577
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595
      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
2596 2597
	if ((eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) && 
	    (eNB->mac_enabled==1)) {
2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625
	  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
2626
  }
2627

2628
}
2629

2630 2631 2632 2633
typedef struct {
  PHY_VARS_eNB *eNB;
  int slot;
} fep_task;
2634

2635
void fep0(PHY_VARS_eNB *eNB,int slot) {
2636

2637 2638 2639
  eNB_proc_t *proc       = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  int l;
2640

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

2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653
  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
		);
  }
}
2654

2655

Raymond Knopp's avatar
Raymond Knopp committed
2656

2657 2658 2659 2660
extern int oai_exit;

static void *fep_thread(void *param) {

2661
  pthread_setname_np( pthread_self(), "UEfep");
2662 2663 2664
  PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param;
  eNB_proc_t *proc  = &eNB->proc;
  while (!oai_exit) {
Raymond Knopp's avatar
Raymond Knopp committed
2665

2666 2667 2668
    if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break;  
    fep0(eNB,0);
    if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
Raymond Knopp's avatar
Raymond Knopp committed
2669 2670 2671 2672

    if (pthread_cond_signal(&proc->cond_fep) != 0) {
      printf("[eNB] ERROR pthread_cond_signal for fep thread exit\n");
      exit_fun( "ERROR pthread_cond_signal" );
2673
      return NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2674
    }
2675
  }
Raymond Knopp's avatar
Raymond Knopp committed
2676 2677 2678 2679 2680 2681



  return(NULL);
}

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

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

2686 2687 2688 2689 2690 2691
  proc->instance_cnt_fep         = -1;
    
  pthread_mutex_init( &proc->mutex_fep, NULL);
  pthread_cond_init( &proc->cond_fep, NULL);

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


2694 2695
}

2696 2697 2698
extern void *td_thread(void*);

void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
2699 2700 2701

  eNB_proc_t *proc = &eNB->proc;

2702 2703
  proc->tdp.eNB = eNB;
  proc->instance_cnt_td         = -1;
2704
    
2705 2706
  pthread_mutex_init( &proc->mutex_td, NULL);
  pthread_cond_init( &proc->cond_td, NULL);
2707

2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725
  pthread_create(&proc->pthread_td, attr_td, td_thread, (void*)&proc->tdp);

}

extern void *te_thread(void*);

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

  eNB_proc_t *proc = &eNB->proc;

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

  printf("Creating te_thread\n");
  pthread_create(&proc->pthread_te, attr_te, te_thread, (void*)&proc->tep);
2726 2727 2728

}

Raymond Knopp's avatar
Raymond Knopp committed
2729

2730
void eNB_fep_full_2thread(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2731 2732

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

2734
  struct timespec wait;
2735

2736 2737 2738 2739 2740 2741 2742
  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) {
2743
    printf("[eNB] ERROR pthread_mutex_lock for fep thread (IC %d)\n", proc->instance_cnt_fep);
2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756
    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;

2757

2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768
  if (pthread_cond_signal(&proc->cond_fep) != 0) {
    printf("[eNB] ERROR pthread_cond_signal for fep thread\n");
    exit_fun( "ERROR pthread_cond_signal" );
    return;
  }
  
  pthread_mutex_unlock( &proc->mutex_fep );

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

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

2771
  stop_meas(&eNB->ofdm_demod_stats);
2772 2773
}

Raymond Knopp's avatar
Raymond Knopp committed
2774 2775


2776
void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2777

2778
  int l;
2779
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2780

2781
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
2782
  start_meas(&eNB->ofdm_demod_stats);
2783 2784
  remove_7_5_kHz(eNB,proc_rxtx->subframe_rx<<1);
  remove_7_5_kHz(eNB,1+(proc_rxtx->subframe_rx<<1));
2785 2786 2787 2788
  for (l=0; l<fp->symbols_per_tti/2; l++) {
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
2789
		(proc_rxtx->subframe_rx)<<1,
Raymond Knopp's avatar
Raymond Knopp committed
2790
		0,
2791 2792 2793 2794 2795
		0
		);
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
2796
		1+((proc_rxtx->subframe_rx)<<1),
2797 2798 2799 2800
		0,
		0
		);
  }
2801
  stop_meas(&eNB->ofdm_demod_stats);
2802 2803 2804 2805 2806
  
  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) **** ///
2807
    LOG_D(PHY,"send_IF4p5 (PULFFT): frame %d, subframe %d\n",proc_rxtx->frame_rx,proc_rxtx->subframe_rx);
2808
    send_IF4p5(eNB, proc_rxtx->frame_rx, proc_rxtx->subframe_rx, IF4p5_PULFFT, 0);
2809 2810 2811 2812
    start_fh_prev = start_fh;
    start_fh_prev_sf = start_fh_sf;
    clock_gettime( CLOCK_MONOTONIC, &start_fh);
    start_fh_sf = proc_rxtx->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
2813
  }    
2814 2815
}

2816
void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2817

Raymond Knopp's avatar
Raymond Knopp committed
2818
  eNB_proc_t *proc=&eNB->proc;
2819 2820 2821 2822 2823
  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);
2824 2825 2826 2827
  start_fh_prev = start_fh;
  start_fh_prev_sf = start_fh_sf;
  clock_gettime( CLOCK_MONOTONIC, &start_fh);
  start_fh_sf = proc->subframe_rx;
2828 2829 2830 2831
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );          

}

2832
void do_prach(PHY_VARS_eNB *eNB,int frame,int subframe) {
2833

Raymond Knopp's avatar
Raymond Knopp committed
2834
  eNB_proc_t *proc = &eNB->proc;
2835 2836 2837
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;

  // check if we have to detect PRACH first
2838
  if (is_prach_subframe(fp,frame,subframe)>0) { 
2839 2840 2841
    /* accept some delay in processing - up to 5ms */
    int i;
    for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) {
2842
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", frame,subframe,proc->instance_cnt_prach);
2843 2844 2845 2846 2847 2848 2849 2850 2851
      usleep(500);
    }
    if (proc->instance_cnt_prach == 0) {
      exit_fun( "PRACH thread busy" );
      return;
    }
    
    // wake up thread for PRACH RX
    if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
Cedric Roux's avatar
Cedric Roux committed
2852
      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach);
2853 2854 2855 2856 2857 2858
      exit_fun( "error locking mutex_prach" );
      return;
    }
    
    ++proc->instance_cnt_prach;
    // set timing for prach thread
2859 2860
    proc->frame_prach = frame;
    proc->subframe_prach = subframe;
2861 2862 2863 2864 2865 2866 2867 2868 2869
    
    // 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 );
2870
  }
2871

2872
}
2873

2874
void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc){
2875 2876


2877
  //  eNB_proc_t *proc       = &eNB->proc;
Raymond Knopp's avatar
Raymond Knopp committed
2878 2879 2880
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  const int subframe     = proc->subframe_rx;
  const int frame        = proc->frame_rx;
2881
  int offset             = (eNB->single_thread_flag==1) ? 0 : (subframe&1);
Sandeep Kumar's avatar
Sandeep Kumar committed
2882

Raymond Knopp's avatar
Raymond Knopp committed
2883 2884
  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 );
2885

Raymond Knopp's avatar
Raymond Knopp committed
2886 2887 2888 2889 2890 2891 2892 2893
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) {

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

2895 2896

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

Raymond Knopp's avatar
Raymond Knopp committed
2900

2901
  if (eNB->fep) eNB->fep(eNB,proc);
2902

Raymond Knopp's avatar
Raymond Knopp committed
2903
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 0 );
2904 2905
}

2906

2907
void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type)
2908
{
2909
  //RX processing for ue-specific resources (i
2910
  UNUSED(r_type);
2911
  uint32_t ret=0,i,j,k;
2912 2913 2914 2915 2916
  uint32_t harq_pid, harq_idx, round;
  uint8_t nPRS;
  int sync_pos;
  uint16_t rnti=0;
  uint8_t access_mode;
2917
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2918

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

2923 2924 2925 2926 2927
  uint16_t srsPeriodicity;
  uint16_t srsOffset;
  uint16_t do_srs=0;
  uint16_t is_srs_pos=0;

2928 2929 2930 2931 2932
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));

  T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
             eNB->frame_parms.samples_per_tti * 4));
2933

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

Raymond Knopp's avatar
Raymond Knopp committed
2936
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
2937

2938
#ifdef DEBUG_PHY_PROC
2939
  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
2940
#endif
2941

2942

2943 2944 2945 2946
  eNB->rb_mask_ul[0]=0;
  eNB->rb_mask_ul[1]=0;
  eNB->rb_mask_ul[2]=0;
  eNB->rb_mask_ul[3]=0;
2947

2948
  // Check for active processes in current subframe
2949
  harq_pid = subframe2harq_pid(fp,
2950
                               frame,subframe);
2951

2952 2953
  // reset the cba flag used for collision detection
  for (i=0; i < NUM_MAX_CBA_GROUP; i++) {
2954
    eNB->cba_last_reception[i]=0;
2955
  }
2956

2957 2958
  is_srs_pos = is_srs_occasion_common(fp,frame,subframe);
  
2959
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2960

2961 2962 2963
    // Do SRS processing 
    // check if there is SRS and we have to use shortened format
    // TODO: check for exceptions in transmission of SRS together with ACK/NACK
2964
    do_srs=0;
2965 2966
    if (is_srs_pos && eNB->soundingrs_ul_config_dedicated[i].srsConfigDedicatedSetup ) {
      compute_srs_pos(fp->frame_type, eNB->soundingrs_ul_config_dedicated[i].srs_ConfigIndex, &srsPeriodicity, &srsOffset);
2967
      if (((10*frame+subframe) % srsPeriodicity) == srsOffset) {
2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
	do_srs = 1;
      }
    }

    if (do_srs==1) {
      if (lte_srs_channel_estimation(fp,
				     &eNB->common_vars,
				     &eNB->srs_vars[i],
				     &eNB->soundingrs_ul_config_dedicated[i],
				     subframe,
				     0/*eNB_id*/)) {
	LOG_E(PHY,"problem processing SRS\n");
      }
    }

    // Do PUCCH processing 

    pucch_procedures(eNB,proc,i,harq_pid, do_srs);

2987

2988
    // check for Msg3
2989
    if (eNB->mac_enabled==1) {
2990
      if (eNB->UE_stats[i].mode == RA_RESPONSE) {
2991
	process_Msg3(eNB,proc,i,harq_pid);
2992 2993
      }
    }
2994 2995


2996 2997 2998
    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;
2999

3000 3001 3002
    if ((eNB->ulsch[i]) &&
        (eNB->ulsch[i]->rnti>0) &&
        (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) {
3003
      // UE is has ULSCH scheduling
3004
      round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
3005
 
3006
      for (int rb=0;
3007
           rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
3008
	   rb++) {
3009
	int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
3010
	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
3011
      }
3012 3013


3014
      if (eNB->ulsch[i]->Msg3_flag == 1) {
3015
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
3016
              eNB->Mod_id,
3017 3018
              frame,
              subframe,
3019
              eNB->UE_stats[i].sector);
3020 3021
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1);
      } else {
3022

3023
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n",
3024
              eNB->Mod_id,
3025 3026 3027
              frame,
              subframe,
              i,
3028
              mode_string[eNB->UE_stats[i].mode]);
3029
      }
3030

3031

3032
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
3033

3034
      eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
3035
				    nPRS)%12;
3036

3037
      if (fp->frame_type == FDD ) {
3038
        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
3039

3040 3041
        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
3042
        } else {
3043
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
3044
        }
3045
      }
3046

3047 3048
      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",
3049
            eNB->Mod_id,harq_pid,frame,subframe,
3050 3051 3052 3053 3054 3055 3056 3057 3058 3059
            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,
3060
            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
3061
            nPRS,
3062 3063 3064 3065
            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;
3066
      start_meas(&eNB->ulsch_demodulation_stats);
3067

3068
      if (eNB->abstraction_flag==0) {
3069
        rx_ulsch(eNB,proc,
3070
                 eNB->UE_stats[i].sector,  // this is the effective sector id
3071
                 i,
3072
                 eNB->ulsch,
3073 3074
                 0);
      }
3075

3076 3077
#ifdef PHY_ABSTRACTION
      else {
3078
        rx_ulsch_emul(eNB,proc,
3079
                      eNB->UE_stats[i].sector,  // this is the effective sector id
3080 3081
                      i);
      }
3082 3083

#endif
3084
      stop_meas(&eNB->ulsch_demodulation_stats);
3085

3086

3087
      start_meas(&eNB->ulsch_decoding_stats);
3088

3089
      if (eNB->abstraction_flag == 0) {
3090
        ret = ulsch_decoding(eNB,proc,
3091 3092
                             i,
                             0, // control_only_flag
3093 3094
                             eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
			     eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
3095
      }
3096

3097
#ifdef PHY_ABSTRACTION
3098
      else {
3099 3100
        ret = ulsch_decoding_emul(eNB,
				  proc,
3101 3102 3103
                                  i,
                                  &rnti);
      }
3104

3105
#endif
3106
      stop_meas(&eNB->ulsch_decoding_stats);
3107

3108
      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",
3109
            eNB->Mod_id,harq_pid,
3110
            frame,subframe,
3111 3112 3113 3114 3115 3116 3117 3118 3119
            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],
3120
            ret);
3121

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

3126
      eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
3127 3128
#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",
3129
            eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
3130
#endif
3131
      eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
3132

3133
      if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) {
3134
#ifdef DEBUG_PHY_PROC
3135
        //if (((frame%10) == 0) || (frame < 50))
3136
        print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
3137
#endif
3138 3139 3140
        extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
                    eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
                    &eNB->UE_stats[i],
3141
                    fp->N_RB_DL,
3142
                    &rnti, &access_mode);
3143
        eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
3144

3145
      }
3146

3147
      if (eNB->ulsch[i]->Msg3_flag == 1)
3148
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
3149

3150
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
3151
        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),
3152
          T_INT(harq_pid));
3153

3154 3155 3156 3157
        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++;
3158

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

3161
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3162

3163
          LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
3164 3165
                eNB->Mod_id,
                eNB->CC_id,
3166
                frame,subframe, i,
3167
                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
3168
                fp->maxHARQ_Msg3Tx-1);
3169 3170
	  /*dump_ulsch(eNB,proc,i);
	    exit(-1);*/
3171

3172
	  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",
3173
		eNB->Mod_id,harq_pid,
3174
		frame,subframe,
3175 3176 3177 3178 3179 3180 3181 3182 3183
		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],
3184
		ret);
3185

3186
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round ==
3187
              fp->maxHARQ_Msg3Tx) {
3188
            LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n",
3189
                  eNB->Mod_id, i);
3190
            eNB->UE_stats[i].mode = PRACH;
3191 3192 3193
	    if (eNB->mac_enabled==1) {
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3194
					frame,
3195
					eNB->UE_stats[i].crnti);
3196
	    }
3197
            mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
3198

3199 3200
            eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
            //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0;
3201 3202

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

3206
            get_Msg3_alloc_ret(fp,
3207
                               subframe,
3208
                               frame,
3209 3210
                               &eNB->ulsch[i]->Msg3_frame,
                               &eNB->ulsch[i]->Msg3_subframe);
Cedric Roux's avatar
Cedric Roux committed
3211

3212 3213 3214
            mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, eNB->ulsch[i]->rnti,
                                         eNB->ulsch[i]->Msg3_frame, eNB->ulsch[i]->Msg3_subframe);

Cedric Roux's avatar
Cedric Roux committed
3215 3216 3217
            T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
              T_INT(i), T_INT(eNB->ulsch[i]->rnti), T_INT(0 /* 0 is for retransmission*/),
              T_INT(eNB->ulsch[i]->Msg3_frame), T_INT(eNB->ulsch[i]->Msg3_subframe));
3218
          }
3219 3220
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
3221

3222 3223
        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",
3224
                eNB->Mod_id,harq_pid,
3225
                frame,subframe, i,
3226 3227 3228 3229
                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]);
3230 3231 3232

#if defined(MESSAGE_CHART_GENERATOR_PHY)
          MSC_LOG_RX_DISCARDED_MESSAGE(
3233 3234 3235 3236 3237 3238 3239
				       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
				       );
3240
#endif
3241

3242
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) {
3243
            LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
3244
                  eNB->Mod_id,harq_pid,
3245
                  frame,subframe, i,
3246
                  eNB->ulsch[i]->Mlimit);
3247

3248 3249 3250 3251
            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++;
3252

Younes's avatar
Younes committed
3253 3254 3255 3256
	   /*if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
		dump_ulsch(eNB,proc,i);
	 	exit(-1);
           }*/
3257
	    // indicate error to MAC
3258 3259 3260 3261 3262 3263 3264 3265 3266
	    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);
3267 3268 3269 3270
          }
        }
      }  // ulsch in error
      else {
3271 3272 3273



3274
        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),
3275 3276
          T_INT(harq_pid));

3277
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3278
	  LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
3279
		eNB->Mod_id,harq_pid,
3280 3281
		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",
3282
		eNB->Mod_id,harq_pid,
3283
		frame,subframe,
3284 3285 3286 3287 3288 3289 3290 3291 3292
		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],
3293 3294 3295 3296
		ret);
	}
#if defined(MESSAGE_CHART_GENERATOR_PHY)
        MSC_LOG_RX_MESSAGE(
3297 3298 3299 3300 3301 3302
			   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
			   );
3303
#endif
3304
        for (j=0; j<fp->nb_antennas_rx; j++)
3305
          //this is the RSSI per RB
3306
          eNB->UE_stats[i].UL_rssi[j] =
3307
	    
3308 3309
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
                     (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
3310
                     fp->ofdm_symbol_size) -
3311 3312
            eNB->rx_total_gain_dB -
            hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
3313
            get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
3314
	    
3315 3316 3317 3318
        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;
3319

3320
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3321
	  if (eNB->mac_enabled==1) {
3322

3323
	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
3324
		  eNB->Mod_id,
3325
		  frame,harq_pid,i);
3326 3327 3328 3329 3330 3331 3332 3333 3334
	    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);
3335 3336
	    
	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
3337 3338
	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	      eNB->UE_stats[i].mode = PRACH;
3339 3340
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3341
					frame,
3342 3343 3344
					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;
3345 3346 3347
	    } // Msg3_flag == 0
	    
	  } // mac_enabled==1
3348

3349 3350
          eNB->UE_stats[i].mode = PUSCH;
          eNB->ulsch[i]->Msg3_flag = 0;
3351

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

3354
          for (k=0; k<8; k++) { //harq_processes
3355 3356 3357 3358
            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;
3359
            }
3360

3361 3362 3363
            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;
3364

3365 3366 3367 3368 3369
            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;
3370
            }
3371 3372
          }

3373 3374 3375
          eNB->UE_stats[i].dlsch_sliding_cnt=0;
          eNB->UE_stats[i].dlsch_NAK_round0=0;
          eNB->UE_stats[i].dlsch_mcs_offset=0;
3376 3377 3378
        } // Msg3_flag==1
	else {  // Msg3_flag == 0

3379
#ifdef DEBUG_PHY_PROC
3380 3381
#ifdef DEBUG_ULSCH
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
3382
                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
3383

3384 3385
          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]);
3386 3387 3388

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

3391
	  if (eNB->mac_enabled==1) {
3392

3393 3394
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
3395
			      frame,subframe,
3396 3397 3398
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
3399 3400
			      harq_pid,
			      NULL);
3401

3402
#ifdef LOCALIZATION
3403 3404
	    start_meas(&eNB->localization_stats);
	    aggregate_eNB_UE_localization_stats(eNB,
3405 3406 3407
						i,
						frame,
						subframe,
3408 3409
						get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
	    stop_meas(&eNB->localization_stats);
3410
#endif
3411 3412 3413
	    
	  } // mac_enabled==1
        } // Msg3_flag == 0
3414

3415
        // estimate timing advance for MAC
3416
        if (eNB->abstraction_flag == 0) {
3417
          sync_pos = lte_est_timing_advance_pusch(eNB,i);
3418
          eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
3419
        }
3420

3421 3422
#ifdef DEBUG_PHY_PROC
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
3423
              eNB->Mod_id,
3424 3425
              frame, subframe,
              i,
3426
              eNB->UE_stats[i].timing_advance_update);
3427
#endif
3428 3429


3430 3431 3432
      }  // ulsch not in error

      // process HARQ feedback
3433
#ifdef DEBUG_PHY_PROC
3434
      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
3435
            eNB->dlsch[i][0]->rnti,
3436 3437
            frame,subframe,
            i);
3438
#endif
3439
      process_HARQ_feedback(i,
3440
                            eNB,proc,
3441 3442 3443 3444 3445 3446 3447
                            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",
3448
            eNB->Mod_id,frame,subframe,
3449
            eNB->UE_stats[i].sector,
3450 3451 3452
            harq_pid,
            i,
            ret,
3453 3454 3455 3456 3457
            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]);
3458 3459 3460 3461
#endif
      
      // dump stats to VCD
      if (i==0) {
3462 3463 3464
	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]);
3465
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
3466 3467
	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
3468
      }
3469
    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
3470 3471


3472
    // update ULSCH statistics for tracing
3473
    if ((frame % 100 == 0) && (subframe == 4)) {
3474
      for (harq_idx=0; harq_idx<8; harq_idx++) {
3475 3476 3477 3478 3479 3480 3481 3482
        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]);
3483
          } else {
3484
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
3485 3486
          }

3487 3488 3489 3490
          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];
3491
        }
3492 3493
      }
    }
3494

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3495
    if ((frame % 100 == 0) && (subframe==4)) {
3496
      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
3497
					eNB->UE_stats[i].total_TBS_last);
3498

3499
      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
3500
    }
3501

3502
    // CBA (non-LTE)
3503
    cba_procedures(eNB,proc,i,harq_pid);
3504 3505
  } // loop i=0 ... NUMBER_OF_UE_MAX-1

3506
  if (eNB->abstraction_flag == 0) {
3507
    lte_eNB_I0_measurements(eNB,
3508 3509
			    subframe,
			    0,
3510 3511
			    eNB->first_run_I0_measurements);
    eNB->first_run_I0_measurements = 0;
3512
  }
3513

3514
#ifdef PHY_ABSTRACTION
3515 3516 3517 3518
  else {
    lte_eNB_I0_measurements_emul(eNB,
				 0);
  }
3519

3520
#endif
3521
  //}
3522 3523

#ifdef EMOS
3524
  phy_procedures_emos_eNB_RX(subframe,eNB);
3525 3526
#endif

3527 3528 3529 3530 3531 3532 3533 3534 3535
#if defined(FLEXRAN_AGENT_SB_IF)
#ifndef DISABLE_SF_TRIGGER
  //Send subframe trigger to the controller
  if (mac_agent_registered[eNB->Mod_id]) {
    agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
  }
#endif
#endif

Raymond Knopp's avatar
Raymond Knopp committed
3536
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
3537

3538
  stop_meas(&eNB->phy_proc_rx);
3539

3540 3541 3542 3543
}

#undef DEBUG_PHY_PROC

Cedric Roux's avatar
Cedric Roux committed
3544
#if defined(Rel10) || defined(Rel14)
3545 3546 3547
int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type)
{

3548
  int do_proc=0;// do nothing
3549 3550

  switch(r_type) {
3551
  case no_relay:
3552
    do_proc= no_relay; // perform the normal eNB operation
3553
    break;
3554

3555
  case multicast_relay:
3556
    if (((next_slot >>1) < 6) || ((next_slot >>1) > 8))
3557
      do_proc = 0; // do nothing
3558 3559 3560
    else // SF#6, SF#7 and SF#8
      do_proc = multicast_relay; // do PHY procedures eNB TX

3561
    break;
3562

3563 3564
  default: // should'not be here
    LOG_W(PHY,"Not supported relay type %d, do nothing\n", r_type);
3565
    do_proc=0;
3566 3567
    break;
  }
3568

3569 3570
  return do_proc;
}
3571 3572
#endif