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

//Agent-related headers
66
#include "ENB_APP/flexran_agent_extern.h"
67
#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
68
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
69

70 71 72 73 74 75
//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

76 77
void exit_fun(const char* s);

78 79
extern int exit_openair;

80 81
// Fix per CC openair rf/if device update
// extern openair0_device openair0;
82

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

88
extern uint16_t hundred_times_log10_NPRB[100];
89

90
unsigned int max_peak_val;
91
int max_sync_pos;
92 93 94 95 96 97 98

//DCI_ALLOC_t dci_alloc[8];

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

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

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

109
uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id)
110
{
Raymond Knopp's avatar
 
Raymond Knopp committed
111

112 113
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
114

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

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

  return(0);
}
138

139

140
int32_t add_ue(int16_t rnti, PHY_VARS_eNB *eNB)
141
{
142
  uint8_t i;
143

144 145

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

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

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

178
int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) {
179
  uint8_t i;
180
  int CC_id;
181
  PHY_VARS_eNB *eNB;
182 183

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

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

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

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

213
int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
214
{
215
  uint8_t i;
216

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

227 228 229
  return(-1);
}

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

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

244 245
  if ((harq_flag == openair_harq_DL) || (harq_flag == openair_harq_RA))  {// this is a DL request

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

248 249 250 251 252 253 254 255 256 257
    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;
      }
    }

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

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

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

284 285 286
  return(0);
}

287
int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
288
{
289
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
290 291
}

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

297
#ifdef EMOS
298
void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB)
299
{
300 301 302 303

}
#endif

304

305

306
void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type)
307 308
{
  UNUSED(r_type);
309
  int subframe = proc->subframe_rx;
310

311
#ifdef DEBUG_PHY_PROC
312
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", eNB->Mod_id,proc->frame_rx, subframe);
313
#endif
314

315

316
  if (eNB->abstraction_flag == 0) {
317
    lte_eNB_I0_measurements(eNB,
318
			    subframe,
319
                            0,
320
                            eNB->first_run_I0_measurements);
Raymond Knopp's avatar
 
Raymond Knopp committed
321
  }
322

323
#ifdef PHY_ABSTRACTION
Raymond Knopp's avatar
 
Raymond Knopp committed
324
  else {
325
    lte_eNB_I0_measurements_emul(eNB,
326
                                 0);
327
  }
328

Raymond Knopp's avatar
 
Raymond Knopp committed
329 330
#endif

331

332 333
}

Raymond Knopp's avatar
 
Raymond Knopp committed
334 335


336
#ifdef EMOS
337
void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *eNB)
338 339
{

340 341
  uint8_t aa;
  uint16_t last_subframe_emos;
342
  uint16_t pilot_pos1 = 3 - eNB->frame_parms.Ncp, pilot_pos2 = 10 - 2*eNB->frame_parms.Ncp;
343
  uint32_t bytes;
344 345 346

  last_subframe_emos=0;

Raymond Knopp's avatar
 
Raymond Knopp committed
347

Raymond Knopp's avatar
 
Raymond Knopp committed
348

Raymond Knopp's avatar
 
Raymond Knopp committed
349

350
#ifdef EMOS_CHANNEL
351

352
  //if (last_slot%2==1) // this is for all UL subframes
353
  if (subframe==3)
354 355 356 357 358 359 360
    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));
361
    }
362

363 364
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
365
  if (subframe==4) {
366
    emos_dump_eNB.timestamp = rt_get_time_ns();
367 368 369 370 371
    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],
372
           sizeof(PHY_MEASUREMENTS_eNB));
373
    memcpy(&emos_dump_eNB.UE_stats[0],&eNB->UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats));
374 375

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

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


#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
#define AMP_OVER_2 (AMP>>1)
394 395
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)};
396

Lionel Gauthier's avatar
Lionel Gauthier committed
397

Raymond Knopp's avatar
 
Raymond Knopp committed
398

Cedric Roux's avatar
Cedric Roux committed
399
unsigned int taus(void);
400
DCI_PDU DCI_pdu_tmp;
Raymond Knopp's avatar
 
Raymond Knopp committed
401

402

403
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,relaying_type_t r_type) {
404 405


406
#ifdef Rel10
407 408
  MCH_PDU *mch_pduP;
  MCH_PDU  mch_pdu;
409
  //  uint8_t sync_area=255;
410
#endif
411

412
  int subframe = proc->subframe_tx;
413

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

485
void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
486

487 488
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int **txdataF = eNB->common_vars.txdataF[0];
489
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
490 491
  int subframe = proc->subframe_tx;
  int frame = proc->frame_tx;
492

493
  // generate Cell-Specific Reference Signals for both slots
494
  if (eNB->abstraction_flag==0) {
495 496 497 498 499 500 501 502 503 504 505 506 507 508
    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);
  }    
509

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

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

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

645
  }
646

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

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

669
}
Raymond Knopp's avatar
 
Raymond Knopp committed
670

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

673
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
674 675
  int frame = proc->frame_tx;
  int subframe = proc->subframe_tx;
676 677 678 679 680 681 682 683 684

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

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

761 762 763 764 765 766
      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,
767
					 eNB->dlsch[(uint8_t)UE_id],
768 769 770 771 772
					 fp,
					 eNB->pdsch_config_dedicated,
					 SI_RNTI,
					 0,
					 P_RNTI,
773
					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single);
774
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
775
	    eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
776 777
      
      
Cedric Roux's avatar
Cedric Roux committed
778 779 780
      T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
        T_INT(dci_alloc->rnti), T_INT(dci_alloc->format),
        T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid));
781

782
      eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
783
      
784
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"/%u\n",eNB->Mod_id,frame,subframe,
785
	    dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]);
786 787 788 789
      
#if defined(SMBV) 
      
      // configure UE-spec DCI
790 791
      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);
792
	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
793
      }
794
      
795
#endif
796 797 798
      
      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,
799
	    frame, subframe,UE_id,
800 801
	    dci_alloc->format,
	    1<<dci_alloc->L);
Raymond Knopp's avatar
 
Raymond Knopp committed
802
    } else {
803
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n",
804
	    eNB->Mod_id,frame,dci_alloc->rnti);
805
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
806
  }
807 808
  
}
809

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

812
  int harq_pid;
813
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
814
  int frame = proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
815
  int subframe = proc->subframe_tx;
816

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

876
}
877

878
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) {
879

880 881
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
882 883 884
  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;
885
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
886 887 888 889
  uint8_t *DLSCH_pdu=NULL;
  uint8_t DLSCH_pdu_tmp[768*8];
  uint8_t DLSCH_pdu_rar[256];
  int i;
890

891 892 893
  LOG_D(PHY,
	"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n",
	eNB->Mod_id, dlsch->rnti,harq_pid,
894
	frame, subframe, input_buffer_length,
895 896 897 898 899
	get_G(fp,
	      dlsch_harq->nb_rb,
	      dlsch_harq->rb_alloc,
	      get_Qm(dlsch_harq->mcs),
	      dlsch_harq->Nl,
900
	      num_pdcch_symbols,frame,subframe),
901 902 903 904 905
	dlsch_harq->nb_rb,
	dlsch_harq->mcs,
	pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	dlsch_harq->rvidx,
	dlsch_harq->round);
906

907
#if defined(MESSAGE_CHART_GENERATOR_PHY)
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
  MSC_LOG_TX_MESSAGE(
		     MSC_PHY_ENB,MSC_PHY_UE,
		     NULL,0,
		     "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
		     frame, subframe,
		     input_buffer_length,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
			   get_Qm(dlsch_harq->mcs),
			   dlsch_harq->Nl,
			   num_pdcch_symbols,frame,subframe),
		     dlsch_harq->nb_rb,
		     dlsch_harq->mcs,
		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
		     dlsch_harq->rvidx,
		     dlsch_harq->round);
#endif

  if (ue_stats) ue_stats->dlsch_sliding_cnt++;

  if (dlsch_harq->round == 0) {

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

934 935 936 937 938 939 940
    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
941
      }
942 943 944 945 946 947 948 949 950 951 952 953 954 955 956
      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;
957
	    
958 959 960 961 962 963 964 965 966 967
	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;
968
	      
969 970 971 972 973
	  generate_eNB_ulsch_params_from_rar(DLSCH_pdu,
					     frame,
					     (subframe),
					     eNB->ulsch[(uint32_t)UE_id],
					     fp);
974
	      
975
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 1;
976
	      
977 978 979 980 981 982 983 984 985 986 987
	  get_Msg3_alloc(fp,
			 subframe,
			 frame,
			 &eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
			 &eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
	  LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n",
		frame,
		subframe,
		UE_id,
		eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
		eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
988
	}
989 990 991 992 993
	if (ue_stats) ue_stats->total_TBS_MAC += dlsch_harq->TBS;
      }
    }
    else {
      DLSCH_pdu = DLSCH_pdu_tmp;
994
	  
995 996 997
      for (i=0; i<input_buffer_length; i++)
	DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
    }
998 999
	
#if defined(SMBV) 
1000

1001 1002 1003 1004 1005
    // 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);
    }
1006

1007
#endif
1008 1009 1010



1011 1012
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1013
    LOG_T(PHY,"eNB DLSCH SDU: \n");
1014

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

1017 1018
    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);
1019

1020

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

1024
    LOG_T(PHY,"\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
1025
#endif
1026
#endif
1027 1028
  } else {
    ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++;
1029 1030
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1031
    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
1032 1033
#endif
#endif
1034
  }
1035

1036
  if (eNB->abstraction_flag==0) {
1037

1038 1039 1040
    LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag);
    // 36-212
    start_meas(&eNB->dlsch_encoding_stats);
1041 1042 1043 1044 1045 1046 1047 1048
    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);
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
    stop_meas(&eNB->dlsch_encoding_stats);
    // 36-211
    start_meas(&eNB->dlsch_scrambling_stats);
    dlsch_scrambling(fp,
		     0,
		     dlsch,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
			   get_Qm(dlsch_harq->mcs),
			   dlsch_harq->Nl,
			   num_pdcch_symbols,frame,subframe),
		     0,
		     subframe<<1);
    stop_meas(&eNB->dlsch_scrambling_stats);
1064

1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
    start_meas(&eNB->dlsch_modulation_stats);


    dlsch_modulation(eNB->common_vars.txdataF[0],
		     AMP,
		     subframe,
		     fp,
		     num_pdcch_symbols,
		     dlsch,
		     dlsch1);
1075
	
1076 1077
    stop_meas(&eNB->dlsch_modulation_stats);
  }
1078 1079


1080
#ifdef PHY_ABSTRACTION
1081 1082 1083 1084 1085 1086 1087
  else {
    start_meas(&eNB->dlsch_encoding_stats);
    dlsch_encoding_emul(eNB,
			DLSCH_pdu,
			dlsch);
    stop_meas(&eNB->dlsch_encoding_stats);
  }
1088

Raymond Knopp's avatar
 
Raymond Knopp committed
1089
#endif
1090
  dlsch->active = 0;
1091
}
1092

1093
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
1094
			   eNB_rxtx_proc_t *proc,
1095
                           relaying_type_t r_type,
1096 1097
			   PHY_VARS_RN *rn,
			   int do_meas)
1098 1099
{
  UNUSED(rn);
1100 1101
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
1102
  //  uint16_t input_buffer_length;
1103 1104 1105 1106
  uint32_t i,aa;
  uint8_t harq_pid;
  DCI_PDU *DCI_pdu;
  DCI_PDU DCI_pdu_tmp;
1107
  int8_t UE_id=0;
1108 1109 1110
  uint8_t num_pdcch_symbols=0;
  uint8_t ul_subframe;
  uint32_t ul_frame;
1111
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1112
  DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL;
1113

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

1116 1117 1118
#if defined(SMBV) 
  // counts number of allocations in subframe
  // there is at least one allocation for PDCCH
1119
  uint8_t smbv_alloc_cnt = 1;Exiting eNB thread RXn_TXnp4
1120

1121
#endif
1122

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

1125
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
1126
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
1127

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1150
  }
1151 1152 1153


  // Get scheduling info for next subframe
1154
  // This is called only for the CC_id = 0 and triggers scheduling for all CC_id's
1155 1156
  if (eNB->mac_enabled==1) {
    if (eNB->CC_id == 0) {
1157
      mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,frame,subframe);//,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1158
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1159
  }
1160

1161
  // clear the transmit data array for the current subframe
1162
  if (eNB->abstraction_flag==0) {
1163
    for (aa=0; aa<fp->nb_antennas_tx_eNB; aa++) {      
1164
      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
1165
             0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
Raymond Knopp's avatar
 
Raymond Knopp committed
1166
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1167
  }
1168

1169
  if (is_pmch_subframe(frame,subframe,fp)) {
1170
    pmch_procedures(eNB,proc,rn,r_type);
1171 1172 1173
  }
  else {
    // this is not a pmch subframe, so generate PSS/SSS/PBCH
1174
    common_signal_procedures(eNB,proc);
1175
  }
1176

1177
#if defined(SMBV) 
1178

Raymond Knopp's avatar
 
Raymond Knopp committed
1179
  // PBCH takes one allocation
1180
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
1181
    if (subframe==0)
Raymond Knopp's avatar
 
Raymond Knopp committed
1182 1183
      smbv_alloc_cnt++;
  }
1184

1185
#endif
1186

1187
  if (eNB->mac_enabled==1) {
1188 1189
    // Parse DCI received from MAC
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
1190 1191
    DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
				     eNB->CC_id,
1192
				     frame,
1193 1194 1195 1196
				     subframe);
  }
  else {
    DCI_pdu = &DCI_pdu_tmp;
1197
#ifdef EMOS_CHANNEL
1198
    fill_dci_emos(DCI_pdu,eNB);
1199
#else
1200
    fill_dci(DCI_pdu,eNB,proc);
1201
#endif
1202
  }
1203

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

1208 1209 1210
  if ((subframe_select(fp,ul_subframe)==SF_UL) ||
      (fp->frame_type == FDD)) {
    harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
1211

1212
    // clear DCI allocation maps for new subframe
1213
    for (i=0; i<NUMBER_OF_UE_MAX; i++)
1214 1215 1216
      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
1217 1218
      }
  }
1219

Raymond Knopp's avatar
 
Raymond Knopp committed
1220
  // clear previous allocation information for all UEs
1221
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
1222 1223
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1224
  }
1225 1226


1227
  num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
Raymond Knopp's avatar
Raymond Knopp committed
1228
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
1229 1230
        DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);

1231
#if defined(SMBV) 
Raymond Knopp's avatar
 
Raymond Knopp committed
1232
  // Sets up PDCCH and DCI table
1233 1234
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) {
    LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",frame,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
1235
    dump_dci(fp,&DCI_pdu->dci_alloc[0]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1236 1237
    smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
  }
1238 1239
#endif

1240 1241
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);

1242
  // loop over all DCIs for this subframe to generate DLSCH allocations
1243 1244 1245 1246 1247
  for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
    LOG_D(PHY,"[eNB] Subframe %d: DCI %d/%d : rnti %x, CCEind %d\n",subframe,i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,DCI_pdu->dci_alloc[i].rnti,DCI_pdu->dci_alloc[i].firstCCE);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].rnti);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].format);
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].firstCCE);
1248
    dci_alloc = &DCI_pdu->dci_alloc[i];
1249

1250 1251 1252 1253
    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);
1254 1255
      else
	UE_id = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1256
    }
1257 1258
    else UE_id=0;
    
1259
    generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
1260

Raymond Knopp's avatar
 
Raymond Knopp committed
1261
  }
1262

1263 1264
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

Raymond Knopp's avatar
 
Raymond Knopp committed
1265
  // Apply physicalConfigDedicated if needed
1266 1267 1268 1269
  // This is for UEs that have received this IE, which changes these DL and UL configuration, we apply after a delay for the eNodeB UL parameters
  phy_config_dedicated_eNB_step2(eNB);
  
  // Now loop again over the DCIs for UL configuration
1270
  for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
Cedric Roux's avatar
Cedric Roux committed
1271
    dci_alloc = &DCI_pdu->dci_alloc[i];
Raymond Knopp's avatar
 
Raymond Knopp committed
1272

1273 1274 1275
    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);
1276 1277
      else
	UE_id = i;
1278
      
1279
      if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
1280
	LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
1281
	mac_xface->macphy_exit("FATAL\n"); 
1282
      }
1283
      generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1284
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1285
  }
1286

1287 1288


Lionel Gauthier's avatar
Lionel Gauthier committed
1289 1290


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

1294 1295

  } else { // for emulation!!
1296 1297
    eNB->num_ue_spec_dci[(subframe)&1]=0;
    eNB->num_common_dci[(subframe)&1]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1298
  }
1299

1300
  if (eNB->abstraction_flag == 0) {
1301

1302
    if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) {
1303
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,frame, subframe,
1304
            DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
1305 1306
    }

1307 1308 1309 1310 1311 1312

    num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_ue_spec_dci,
                                         DCI_pdu->Num_common_dci,
                                         DCI_pdu->dci_alloc,
                                         0,
                                         AMP,
1313
                                         fp,
1314
                                         eNB->common_vars.txdataF[0],
1315
                                         subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1316

Raymond Knopp's avatar
 
Raymond Knopp committed
1317
  }
1318

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

1325 1326
#endif

1327
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
1328

Raymond Knopp's avatar
 
Raymond Knopp committed
1329
  // Check for SI activity
1330

1331
  if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
1332

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

1335
#if defined(SMBV) 
1336

Raymond Knopp's avatar
 
Raymond Knopp committed
1337
    // Configures the data source of allocation (allocation is configured by DCI)
1338 1339
    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
1340 1341
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
    }
1342 1343

#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1344
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1345

Raymond Knopp's avatar
 
Raymond Knopp committed
1346
  // Check for RA activity
1347
  if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
1348

1349
#if defined(SMBV) 
1350

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

1372 1373
#ifndef DISABLE_SF_TRIGGER
  //Send subframe trigger to the controller
1374
  if (mac_agent_registered[eNB->Mod_id]) {
1375
    agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
1376 1377 1378
  }
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1379
  // Now scan UE specific DLSCH
1380
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
1381 1382 1383 1384
    {
      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)) {
1385

1386
	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);
1387 1388


Raymond Knopp's avatar
 
Raymond Knopp committed
1389
      }
1390

1391 1392 1393
      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)) {
1394

1395 1396
	// 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
1397
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1398
    }
1399

1400 1401


Raymond Knopp's avatar
 
Raymond Knopp committed
1402
  // if we have PHICH to generate
1403

1404
  if (is_phich_subframe(fp,subframe))
1405 1406 1407 1408
    {
      generate_phich_top(eNB,
			 proc,
			 AMP,
1409
			 0);
1410
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1411

1412 1413


1414
#ifdef EMOS
1415
  phy_procedures_emos_eNB_TX(subframe, eNB);
Raymond Knopp's avatar
 
Raymond Knopp committed
1416
#endif
1417

1418
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
1419
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
1420
  
1421 1422
}

1423
void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid)
1424
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1425
  // this prepares the demodulation of the first PUSCH of a new user, containing Msg3
1426 1427
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1428

Raymond Knopp's avatar
 
Raymond Knopp committed
1429
  LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
1430
        eNB->Mod_id,
1431
        frame,subframe,
1432 1433 1434 1435
        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;
1436

1437 1438 1439
  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))   {
1440

1441
    //    harq_pid = 0;
1442

1443 1444 1445
    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
1446
    LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
1447
          eNB->Mod_id,
1448
          frame,subframe,UE_id);
1449 1450 1451 1452 1453 1454 1455 1456 1457
  }
}


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

1458
void process_HARQ_feedback(uint8_t UE_id,
1459
                           PHY_VARS_eNB *eNB,
1460
			   eNB_rxtx_proc_t *proc,
1461 1462 1463 1464 1465
                           uint8_t pusch_flag,
                           uint8_t *pucch_payload,
                           uint8_t pucch_sel,
                           uint8_t SR_payload)
{
1466

1467
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1468
  uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe;
1469 1470
  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];
1471
  LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
1472
  uint8_t subframe_m4,M,m;
1473 1474
  int mp;
  int all_ACKed=1,nb_alloc=0,nb_ACK=0;
1475 1476
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1477
  int harq_pid = subframe2harq_pid( fp,frame,subframe);
1478 1479


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

1483 1484
    dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
    M=1;
1485

1486
    if (pusch_flag == 1) {
1487
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1488
      if (dlsch->subframe_tx[subframe_m4]==1)
1489 1490
	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);
1491 1492
    }
    else {
1493
      dlsch_ACK[0] = pucch_payload[0];
1494
      LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",eNB->Mod_id,
1495
	    frame,dlsch_ACK[0],subframe_m4);
kaltenbe's avatar
kaltenbe committed
1496
      /*
1497
	if (dlsch_ACK[0]==0)
1498
	AssertFatal(0,"Exiting on NAK on PUCCH\n");
kaltenbe's avatar
kaltenbe committed
1499
      */
1500
    }
1501

Lionel Gauthier's avatar
Lionel Gauthier committed
1502 1503 1504

#if defined(MESSAGE_CHART_GENERATOR_PHY)
    MSC_LOG_RX_MESSAGE(
1505 1506 1507 1508 1509 1510 1511 1512 1513 1514
		       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
1515
#endif
1516 1517
  } else { // TDD Handle M=1,2 cases only

1518
    M=ul_ACK_subframe2_M(fp,
1519 1520
                         subframe);

1521 1522 1523 1524 1525 1526 1527 1528
    // 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

1529
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1530
      dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling)
1531
	?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];
1532
    }
1533

1534
    else {  // PUCCH ACK/NAK
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569
      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;
        }
1570
      }
1571
    }
1572 1573 1574 1575
  }

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

    for (m=0; m<M; m++) {
1579
      dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1580 1581
						 subframe,
						 m);
1582 1583 1584

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

1587 1588
    if (nb_alloc == nb_ACK)
      all_ACKed = 1;
1589
    else
1590
      all_ACKed = 0;
1591 1592 1593
  }


1594
  for (m=0,mp=-1; m<M; m++) {
1595

1596
    dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1597 1598
					       subframe,
					       m);
1599

1600 1601
    if (dlsch->subframe_tx[dl_subframe]==1) {
      if (pusch_flag == 1)
1602
        mp++;
1603
      else
1604
        mp = m;
1605

1606
      dl_harq_pid[m]     = dlsch->harq_ids[dl_subframe];
1607

1608
      if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
1609 1610 1611 1612
        if ((SR_payload == 1)&&(all_ACKed == 1))
          dlsch_ACK[m] = 1;
        else
          dlsch_ACK[m] = 0;
1613
      }
1614

1615
      if (dl_harq_pid[m]<dlsch->Mdlharq) {
1616 1617
        dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
1618
        LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id,
1619 1620 1621 1622 1623 1624 1625 1626 1627
              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");

1628
#endif
1629 1630 1631 1632 1633 1634 1635 1636

        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
1637
            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,
1638
                  dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
1639
#endif
1640

1641
            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),
1642
              T_INT(dl_harq_pid[m]));
1643

1644 1645 1646 1647 1648 1649 1650 1651 1652
            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++;

1653

1654
            if (dlsch_harq_proc->round == dlsch->Mlimit) {
1655 1656
              // This was the last round for DLSCH so reset round and increment l2_error counter
#ifdef DEBUG_PHY_PROC
1657
              LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",eNB->Mod_id,
1658
                    dlsch->rnti,dl_harq_pid[m]);
1659
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1660
#if defined(MESSAGE_CHART_GENERATOR_PHY)
1661
              MSC_LOG_EVENT(MSC_PHY_ENB, "0 HARQ DLSCH Failed RNTI %"PRIx16" round %u",
1662 1663
                            dlsch->rnti,
                            dlsch_harq_proc->round);
Lionel Gauthier's avatar
Lionel Gauthier committed
1664
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1665

1666 1667 1668 1669 1670 1671 1672
              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
1673
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
1674
                  dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
1675
#endif
1676

1677
            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),
1678
              T_INT(dl_harq_pid[m]));
1679

1680 1681 1682 1683 1684 1685 1686 1687
            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 +
1688
	      eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1689 1690
            /*
              ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
1691
              eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705
            */
          }

          // 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);
1706
#endif
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728

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


        }
1729
      }
1730
    }
1731 1732 1733
  }
}

1734
void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
1735
		      eNB_rxtx_proc_t *proc,
1736 1737 1738 1739 1740 1741
                      uint8_t UE_id,
                      int16_t *n1_pucch0,
                      int16_t *n1_pucch1,
                      int16_t *n1_pucch2,
                      int16_t *n1_pucch3)
{
1742

1743
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
1744
  uint8_t nCCE0,nCCE1;
1745
  int sf;
1746 1747
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1748 1749

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

1752 1753
    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];
1754
      *n1_pucch1 = -1;
1755
    } else {
1756 1757 1758
      *n1_pucch0 = -1;
      *n1_pucch1 = -1;
    }
1759
  } else {
1760

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

1771 1772
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1773 1774 1775 1776 1777 1778 1779
          *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

1780 1781
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1782 1783 1784 1785 1786 1787 1788 1789 1790
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;

        *n1_pucch1 = -1;

      } else if (subframe == 7) { // ACK subframes 0 and 1
        //harq_ack[0].nCCE;
        //harq_ack[1].nCCE;
1791 1792
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1793 1794 1795 1796 1797 1798 1799
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;

        *n1_pucch1 = -1;
      } else if (subframe == 8) { // ACK subframes 4
        //harq_ack[4].nCCE;
1800 1801
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4];
1802 1803 1804 1805 1806 1807 1808
          *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",
1809
              eNB->Mod_id,
1810 1811 1812
              frame,
              subframe,frame_parms->tdd_config);
        return;
1813
      }
1814

1815
      break;
1816

1817 1818
    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)
1819 1820
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
1821 1822 1823 1824
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

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

1834 1835
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[8];
1836 1837 1838 1839 1840
          *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;

1841 1842
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7];
1843 1844 1845 1846 1847
          *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
1848 1849
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1850 1851 1852 1853
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1854 1855
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1856 1857 1858 1859 1860
          *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",
1861
              eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
1862
        return;
1863
      }
1864

1865
      break;
1866 1867
    }  // switch tdd_config

1868 1869 1870
    // Don't handle the case M>2
    *n1_pucch2 = -1;
    *n1_pucch3 = -1;
1871 1872 1873
  }
}

1874
void prach_procedures(PHY_VARS_eNB *eNB) {
1875

1876
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1877 1878 1879 1880
  uint16_t preamble_energy_list[64],preamble_delay_list[64];
  uint16_t preamble_max,preamble_energy_max;
  uint16_t i;
  int8_t UE_id;
1881 1882
  int subframe = eNB->proc.subframe_prach;
  int frame = eNB->proc.frame_prach;
1883
  uint8_t CC_id = eNB->CC_id;
1884

1885
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
1886 1887
  memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
  memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
1888

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

1893

1894
    rx_prach(eNB,
1895 1896 1897 1898 1899 1900 1901
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
  } else {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {

1902
      LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
1903
            UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
1904
            PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
1905
            fp->prach_config_common.rootSequenceIndex,
1906 1907
            PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex);

Raymond Knopp's avatar
 
Raymond Knopp committed
1908
      if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) &&
1909
          (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex ==
1910
           fp->prach_config_common.rootSequenceIndex) ) {
1911 1912 1913
        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;

1914
      }
1915
    }
1916
  }
1917

1918 1919 1920
  preamble_energy_max = preamble_energy_list[0];
  preamble_max = 0;

1921
  for (i=1; i<64; i++) {
1922 1923 1924 1925
    if (preamble_energy_max < preamble_energy_list[i]) {
      preamble_energy_max = preamble_energy_list[i];
      preamble_max = i;
    }
1926 1927 1928
  }

#ifdef DEBUG_PHY_PROC
1929
  LOG_D(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
1930 1931 1932
        preamble_max,
        preamble_energy_list[preamble_max],
        preamble_delay_list[preamble_max]);
1933 1934
#endif

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

1937
    UE_id = find_next_ue_index(eNB);
1938
 
1939
    if (UE_id>=0) {
1940
      eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
1941

1942
      eNB->UE_stats[(uint32_t)UE_id].sector = 0;
1943
      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",
1944 1945
            eNB->Mod_id,
            eNB->CC_id,
1946 1947
            frame,
            subframe,
1948
	    UE_id,
1949 1950 1951 1952
            preamble_max,
            preamble_energy_max/10,
            preamble_energy_max%10,
            preamble_delay_list[preamble_max]);
1953

1954
      if (eNB->mac_enabled==1) {
1955 1956
        uint8_t update_TA=4;

1957
        switch (fp->N_RB_DL) {
1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974
        case 6:
          update_TA = 16;
          break;

        case 25:
          update_TA = 4;
          break;

        case 50:
          update_TA = 2;
          break;

        case 100:
          update_TA = 1;
          break;
        }

1975 1976 1977 1978 1979 1980
	mac_xface->initiate_ra_proc(eNB->Mod_id,
				    eNB->CC_id,
				    frame,
				    preamble_max,
				    preamble_delay_list[preamble_max]*update_TA,
				    0,subframe,0);
1981 1982
      }      

1983
    } else {
1984
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many");
1985
      LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
1986
            eNB->Mod_id,frame, subframe);
1987
    }
1988
  }
1989
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
1990 1991
}

1992
void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
1993

1994
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1995
  uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0};
1996 1997 1998
  int16_t n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3;
  uint8_t do_SR = 0;
  uint8_t pucch_sel = 0;
1999
  int32_t metric0=0,metric1=0,metric0_SR=0;
2000 2001
  ANFBmode_t bundling_flag;
  PUCCH_FMT_t format;
2002 2003
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2004

2005 2006 2007
  if ((eNB->dlsch[UE_id][0]) &&
      (eNB->dlsch[UE_id][0]->rnti>0) &&
      (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { 
2008

2009
    // check SR availability
2010 2011 2012
    do_SR = is_SR_subframe(eNB,proc,UE_id);
    //      do_SR = 0;
    
2013 2014
    // Now ACK/NAK
    // First check subframe_tx flag for earlier subframes
2015

2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
    get_n1_pucch_eNB(eNB,
		     proc,
		     UE_id,
		     &n1_pucch0,
		     &n1_pucch1,
		     &n1_pucch2,
		     &n1_pucch3);
    
    LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d, subframe %d Checking for PUCCH (%d,%d,%d,%d) SR %d\n",
	  eNB->Mod_id,eNB->dlsch[UE_id][0]->rnti,
	  frame,subframe,
	  n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR);
    
    if ((n1_pucch0==-1) && (n1_pucch1==-1) && (do_SR==0)) {  // no TX PDSCH that have to be checked and no SR for this UE_id
    } else {
      // otherwise we have some PUCCH detection to do
      
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
	eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
	break;
      case 15:
	eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
	break;
      case 25:
	eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
	break;
      case 50:
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
	break;
      case 75:
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
	break;
      case 100:
	eNB->rb_mask_ul[0] |= 0x1;
	eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
	break;
      default:
	LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
	break;
      }
      
      if (do_SR == 1) {
	eNB->UE_stats[UE_id].sr_total++;
2063 2064


2065
	if (eNB->abstraction_flag == 0)
2066 2067 2068 2069 2070 2071 2072
	  metric0_SR = rx_pucch(eNB,
				pucch_format1,
				UE_id,
				eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
				0, // n2_pucch
				0, // shortened format, should be use_srs flag, later
				&SR_payload,
2073
				frame,
2074 2075 2076
				subframe,
				PUCCH1_THRES);
	
2077
#ifdef PHY_ABSTRACTION
2078 2079
	else {
	  metric0_SR = rx_pucch_emul(eNB,
2080
				     proc,
2081 2082 2083 2084 2085 2086 2087 2088
				     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);
	}
	
2089
#endif
2090

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

2218 2219
    } // FDD
    else {  //TDD
2220

2221
      bundling_flag = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode;
2222

2223
      // fix later for 2 TB case and format1b
Raymond Knopp's avatar
Raymond Knopp committed
2224

2225 2226 2227 2228 2229 2230 2231
      if ((fp->frame_type==FDD) ||
	  (bundling_flag==bundling)    ||
	  ((fp->frame_type==TDD)&&(fp->tdd_config==1)&&((subframe!=2)||(subframe!=7)))) {
	format = pucch_format1a;
      } else {
	format = pucch_format1b;
      }
2232

2233 2234
      // if SR was detected, use the n1_pucch from SR
      if (SR_payload==1) {
2235
#ifdef DEBUG_PHY_PROC
2236 2237 2238 2239
	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);
2240
#endif
2241

2242
	if (eNB->abstraction_flag == 0)
2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253
	  metric0_SR = rx_pucch(eNB,
				format,
				UE_id,
				eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
				0, //n2_pucch
				0, // shortened format
				pucch_payload0,
				frame,
				subframe,
				PUCCH1a_THRES);
	else {
2254
#ifdef PHY_ABSTRACTION
2255 2256 2257 2258 2259
	  metric0 = rx_pucch_emul(eNB,proc,
				  UE_id,
				  format,
				  0,
				  pucch_payload0);
2260
#endif
2261 2262
	}
      } else { //using n1_pucch0/n1_pucch1 resources
2263
#ifdef DEBUG_PHY_PROC
2264 2265 2266 2267 2268 2269 2270 2271 2272 2273
	LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",eNB->Mod_id,
	      eNB->dlsch[UE_id][0]->rnti,
	      frame,subframe,
	      n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
#endif
	metric0=0;
	metric1=0;

	// Check n1_pucch0 metric
	if (n1_pucch0 != -1) {
2274
	  if (eNB->abstraction_flag == 0)
2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285
	    metric0 = rx_pucch(eNB,
			       format,
			       UE_id,
			       (uint16_t)n1_pucch0,
			       0, // n2_pucch
			       0, // shortened format
			       pucch_payload0,
			       frame,
			       subframe,
			       PUCCH1a_THRES);
	  else {
2286
#ifdef PHY_ABSTRACTION
2287 2288 2289 2290 2291 2292
	    metric0 = rx_pucch_emul(eNB,
				    proc,
				    UE_id,
				    format,
				    0,
				    pucch_payload0);
2293
#endif
2294 2295
	  }
	}
2296

2297 2298
	// Check n1_pucch1 metric
	if (n1_pucch1 != -1) {
2299
	  if (eNB->abstraction_flag == 0)
2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310
	    metric1 = rx_pucch(eNB,
			       format,
			       UE_id,
			       (uint16_t)n1_pucch1,
			       0, //n2_pucch
			       0, // shortened format
			       pucch_payload1,
			       frame,
			       subframe,
			       PUCCH1a_THRES);
	  else {
2311
#ifdef PHY_ABSTRACTION
2312 2313 2314 2315 2316 2317
	    metric1 = rx_pucch_emul(eNB,
				    proc,
				    UE_id,
				    format,
				    1,
				    pucch_payload1);
2318
#endif
2319 2320 2321
	  }
	}
      }
2322

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

2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350
#ifdef DEBUG_PHY_PROC
      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, sel %d, (%d,%d)\n",eNB->Mod_id,
	    eNB->dlsch[UE_id][0]->rnti,
	    frame,subframe,
	    metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]);
#endif
      process_HARQ_feedback(UE_id,eNB,proc,
			    0,// pusch_flag
			    pucch_payload,
			    pucch_sel,
			    SR_payload);
2351
    }
2352
  }  
2353
}
2354

2355

2356
void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
2357

2358 2359
  uint8_t access_mode;
  int num_active_cba_groups;
2360 2361
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2362 2363
  uint16_t rnti=0;
  int ret=0;
2364
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2365

2366 2367
  if (eNB->ulsch[UE_id]==NULL) return;

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

2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462
    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;
2463 2464
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482
      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
2483 2484
	if ((eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) && 
	    (eNB->mac_enabled==1)) {
2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
	  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
2513
  }
2514

2515
}
2516

2517 2518 2519 2520
typedef struct {
  PHY_VARS_eNB *eNB;
  int slot;
} fep_task;
2521

2522
void fep0(PHY_VARS_eNB *eNB,int slot) {
2523

2524 2525 2526
  eNB_proc_t *proc       = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  int l;
2527

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

2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540
  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
		);
  }
}
2541

2542

Raymond Knopp's avatar
Raymond Knopp committed
2543

2544 2545 2546 2547 2548 2549 2550
extern int oai_exit;

static void *fep_thread(void *param) {

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

2552 2553 2554
    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
2555 2556 2557 2558

    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" );
2559
      return NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2560
    }
2561
  }
Raymond Knopp's avatar
Raymond Knopp committed
2562 2563 2564 2565 2566 2567



  return(NULL);
}

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

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

2572 2573 2574 2575 2576 2577
  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
2578 2579


2580 2581
}

2582 2583 2584
extern void *td_thread(void*);

void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
2585 2586 2587

  eNB_proc_t *proc = &eNB->proc;

2588 2589
  proc->tdp.eNB = eNB;
  proc->instance_cnt_td         = -1;
2590
    
2591 2592
  pthread_mutex_init( &proc->mutex_td, NULL);
  pthread_cond_init( &proc->cond_td, NULL);
2593

2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611
  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);
2612 2613 2614

}

Raymond Knopp's avatar
Raymond Knopp committed
2615

2616 2617 2618
void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) {

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

2620
  struct timespec wait;
2621

2622 2623 2624 2625 2626 2627 2628
  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) {
2629
    printf("[eNB] ERROR pthread_mutex_lock for fep thread (IC %d)\n", proc->instance_cnt_fep);
2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642
    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;

2643

2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654
  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
2655
  wait_on_busy_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread");  
2656

2657
  stop_meas(&eNB->ofdm_demod_stats);
2658 2659
}

Raymond Knopp's avatar
Raymond Knopp committed
2660 2661


Raymond Knopp's avatar
Raymond Knopp committed
2662
void eNB_fep_full(PHY_VARS_eNB *eNB) {
2663

Raymond Knopp's avatar
Raymond Knopp committed
2664
  eNB_proc_t *proc = &eNB->proc;
2665
  int l;
2666
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2667

2668
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
2669
  start_meas(&eNB->ofdm_demod_stats);
2670 2671 2672 2673 2674 2675 2676
  remove_7_5_kHz(eNB,proc->subframe_rx<<1);
  remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1));
  for (l=0; l<fp->symbols_per_tti/2; l++) {
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		proc->subframe_rx<<1,
Raymond Knopp's avatar
Raymond Knopp committed
2677
		0,
2678 2679 2680 2681 2682 2683 2684 2685 2686 2687
		0
		);
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		1+(proc->subframe_rx<<1),
		0,
		0
		);
  }
2688
  stop_meas(&eNB->ofdm_demod_stats);
2689 2690 2691 2692 2693 2694
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
  
  if (eNB->node_function == NGFI_RRU_IF4p5) {
    /// **** send_IF4 of rxdataF to RCC (no prach now) **** ///
    send_IF4p5(eNB, proc->frame_rx, proc->subframe_rx, IF4p5_PULFFT, 0);
Raymond Knopp's avatar
Raymond Knopp committed
2695
  }    
2696 2697
}

Raymond Knopp's avatar
Raymond Knopp committed
2698
void eNB_fep_rru_if5(PHY_VARS_eNB *eNB) {
2699

Raymond Knopp's avatar
Raymond Knopp committed
2700
  eNB_proc_t *proc=&eNB->proc;
2701 2702 2703 2704 2705 2706 2707 2708 2709
  uint8_t seqno=0;

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

}

Raymond Knopp's avatar
Raymond Knopp committed
2710
void do_prach(PHY_VARS_eNB *eNB) {
2711

Raymond Knopp's avatar
Raymond Knopp committed
2712
  eNB_proc_t *proc = &eNB->proc;
2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;

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

2750
}
2751

2752 2753 2754
void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){


Raymond Knopp's avatar
Raymond Knopp committed
2755 2756 2757 2758
  eNB_proc_t *proc       = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  const int subframe     = proc->subframe_rx;
  const int frame        = proc->frame_rx;
2759
  int offset             = (eNB->single_thread_flag==1) ? 0 : (subframe&1);
Sandeep Kumar's avatar
Sandeep Kumar committed
2760

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

Raymond Knopp's avatar
Raymond Knopp committed
2763 2764 2765
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB+offset, proc->frame_rx );
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+offset, proc->subframe_rx );
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 1 );
2766
  
2767
  start_meas(&eNB->phy_proc_rx);
2768
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe);
2769

Raymond Knopp's avatar
Raymond Knopp committed
2770

Raymond Knopp's avatar
Raymond Knopp committed
2771
  if (eNB->fep) eNB->fep(eNB);
2772

Raymond Knopp's avatar
Raymond Knopp committed
2773
  if (eNB->do_prach) eNB->do_prach(eNB);
2774

Raymond Knopp's avatar
Raymond Knopp committed
2775
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 0 );
2776 2777
}

2778

2779
void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type)
2780
{
2781
  //RX processing for ue-specific resources (i
2782
  UNUSED(r_type);
2783
  uint32_t ret=0,i,j,k;
2784 2785 2786 2787 2788
  uint32_t harq_pid, harq_idx, round;
  uint8_t nPRS;
  int sync_pos;
  uint16_t rnti=0;
  uint8_t access_mode;
2789
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2790

2791
  const int subframe = proc->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
2792 2793
  const int frame    = proc->frame_rx;
  int offset         = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1;
2794

2795

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

Raymond Knopp's avatar
Raymond Knopp committed
2798
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
2799

2800
#ifdef DEBUG_PHY_PROC
2801
  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
2802
#endif
2803

2804
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
2805

2806
  T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
Cedric Roux's avatar
Cedric Roux committed
2807
    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
2808
             eNB->frame_parms.samples_per_tti * 4));
2809

2810 2811 2812 2813
  eNB->rb_mask_ul[0]=0;
  eNB->rb_mask_ul[1]=0;
  eNB->rb_mask_ul[2]=0;
  eNB->rb_mask_ul[3]=0;
2814

2815 2816


2817
  // Check for active processes in current subframe
2818
  harq_pid = subframe2harq_pid(fp,
2819
                               frame,subframe);
2820

2821 2822
  // reset the cba flag used for collision detection
  for (i=0; i < NUM_MAX_CBA_GROUP; i++) {
2823
    eNB->cba_last_reception[i]=0;
2824
  }
2825

2826
  // Do PUCCH processing first
2827

2828
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2829
    pucch_procedures(eNB,proc,i,harq_pid);
2830
  }
2831

2832
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2833

2834
    // check for Msg3
2835
    if (eNB->mac_enabled==1) {
2836
      if (eNB->UE_stats[i].mode == RA_RESPONSE) {
2837
	process_Msg3(eNB,proc,i,harq_pid);
2838 2839
      }
    }
2840 2841


2842 2843 2844
    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;
2845

2846 2847 2848
    if ((eNB->ulsch[i]) &&
        (eNB->ulsch[i]->rnti>0) &&
        (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) {
2849
      // UE is has ULSCH scheduling
2850
      round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
2851
 
2852
      for (int rb=0;
2853
           rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
2854
	   rb++) {
2855
	int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
2856
	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
2857
      }
2858 2859


2860
      if (eNB->ulsch[i]->Msg3_flag == 1) {
2861
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
2862
              eNB->Mod_id,
2863 2864
              frame,
              subframe,
2865
              eNB->UE_stats[i].sector);
2866 2867
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1);
      } else {
2868

2869
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n",
2870
              eNB->Mod_id,
2871 2872 2873
              frame,
              subframe,
              i,
2874
              mode_string[eNB->UE_stats[i].mode]);
2875
      }
2876

2877

2878
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
2879

2880
      eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
2881
				    nPRS)%12;
2882

2883
      if (fp->frame_type == FDD ) {
2884
        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
2885

2886 2887
        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
2888
        } else {
2889
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
2890
        }
2891
      }
2892

2893 2894
      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",
2895
            eNB->Mod_id,harq_pid,frame,subframe,
2896 2897 2898 2899 2900 2901 2902 2903 2904 2905
            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,
2906
            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
2907
            nPRS,
2908 2909 2910 2911
            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;
2912
      start_meas(&eNB->ulsch_demodulation_stats);
2913

2914
      if (eNB->abstraction_flag==0) {
2915
        rx_ulsch(eNB,proc,
2916
                 eNB->UE_stats[i].sector,  // this is the effective sector id
2917
                 i,
2918
                 eNB->ulsch,
2919 2920
                 0);
      }
2921

2922 2923
#ifdef PHY_ABSTRACTION
      else {
2924
        rx_ulsch_emul(eNB,proc,
2925
                      eNB->UE_stats[i].sector,  // this is the effective sector id
2926 2927
                      i);
      }
2928 2929

#endif
2930
      stop_meas(&eNB->ulsch_demodulation_stats);
2931

2932

2933
      start_meas(&eNB->ulsch_decoding_stats);
2934

2935
      if (eNB->abstraction_flag == 0) {
2936
        ret = ulsch_decoding(eNB,proc,
2937 2938
                             i,
                             0, // control_only_flag
2939 2940
                             eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
			     eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2941
      }
2942

2943
#ifdef PHY_ABSTRACTION
2944
      else {
2945 2946
        ret = ulsch_decoding_emul(eNB,
				  proc,
2947 2948 2949
                                  i,
                                  &rnti);
      }
2950

2951
#endif
2952
      stop_meas(&eNB->ulsch_decoding_stats);
2953

2954
      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",
2955
            eNB->Mod_id,harq_pid,
2956
            frame,subframe,
2957 2958 2959 2960 2961 2962 2963 2964 2965
            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],
2966
            ret);
2967

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

2972
      eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
2973 2974
#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",
2975
            eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
2976
#endif
2977
      eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
2978

2979
      if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2980
#ifdef DEBUG_PHY_PROC
2981
        //if (((frame%10) == 0) || (frame < 50))
2982
        print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
2983
#endif
2984 2985 2986
        extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
                    eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
                    &eNB->UE_stats[i],
2987
                    fp->N_RB_DL,
2988
                    &rnti, &access_mode);
2989
        eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
2990

2991
      }
2992

2993
      if (eNB->ulsch[i]->Msg3_flag == 1)
2994
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
2995

2996
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
2997
        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),
2998
          T_INT(harq_pid));
2999

3000 3001 3002 3003
        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++;
3004

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

3007
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3008
          LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
3009 3010
                eNB->Mod_id,
                eNB->CC_id,
3011
                frame,subframe, i,
3012
                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
3013
                fp->maxHARQ_Msg3Tx-1);
3014

3015
	  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",
3016
		eNB->Mod_id,harq_pid,
3017
		frame,subframe,
3018 3019 3020 3021 3022 3023 3024 3025 3026
		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],
3027
		ret);
3028

3029
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round ==
3030
              fp->maxHARQ_Msg3Tx) {
3031
            LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n",
3032
                  eNB->Mod_id, i);
3033
            eNB->UE_stats[i].mode = PRACH;
3034 3035 3036
	    if (eNB->mac_enabled==1) {
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3037
					frame,
3038
					eNB->UE_stats[i].crnti);
3039
	    }
3040
            mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
3041

3042 3043
            eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
            //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0;
3044 3045

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

3049
            get_Msg3_alloc_ret(fp,
3050
                               subframe,
3051
                               frame,
3052 3053
                               &eNB->ulsch[i]->Msg3_frame,
                               &eNB->ulsch[i]->Msg3_subframe);
3054
          }
3055 3056
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
3057

3058 3059
        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",
3060
                eNB->Mod_id,harq_pid,
3061
                frame,subframe, i,
3062 3063 3064 3065
                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]);
3066 3067 3068

#if defined(MESSAGE_CHART_GENERATOR_PHY)
          MSC_LOG_RX_DISCARDED_MESSAGE(
3069 3070 3071 3072 3073 3074 3075
				       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
				       );
3076
#endif
3077

3078
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) {
3079
            LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
3080
                  eNB->Mod_id,harq_pid,
3081
                  frame,subframe, i,
3082
                  eNB->ulsch[i]->Mlimit);
3083

3084 3085 3086 3087
            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++;
3088 3089

	    // indicate error to MAC
3090 3091 3092 3093 3094 3095 3096 3097 3098
	    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);
3099 3100 3101 3102
          }
        }
      }  // ulsch in error
      else {
3103 3104 3105



3106
        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),
3107 3108
          T_INT(harq_pid));

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

3152
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3153
	  if (eNB->mac_enabled==1) {
3154

3155
	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
3156
		  eNB->Mod_id,
3157
		  frame,harq_pid,i);
3158 3159 3160 3161 3162 3163 3164 3165 3166
	    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);
3167 3168
	    
	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
3169 3170
	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	      eNB->UE_stats[i].mode = PRACH;
3171 3172
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3173
					frame,
3174 3175 3176
					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;
3177 3178 3179
	    } // Msg3_flag == 0
	    
	  } // mac_enabled==1
3180

3181 3182
          eNB->UE_stats[i].mode = PUSCH;
          eNB->ulsch[i]->Msg3_flag = 0;
3183

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

3186
          for (k=0; k<8; k++) { //harq_processes
3187 3188 3189 3190
            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;
3191
            }
3192

3193 3194 3195
            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;
3196

3197 3198 3199 3200 3201
            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;
3202
            }
3203 3204
          }

3205 3206 3207
          eNB->UE_stats[i].dlsch_sliding_cnt=0;
          eNB->UE_stats[i].dlsch_NAK_round0=0;
          eNB->UE_stats[i].dlsch_mcs_offset=0;
3208 3209 3210
        } // Msg3_flag==1
	else {  // Msg3_flag == 0

3211
#ifdef DEBUG_PHY_PROC
3212 3213
#ifdef DEBUG_ULSCH
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
3214
                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
3215

3216 3217
          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]);
3218 3219 3220

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

3223
	  if (eNB->mac_enabled==1) {
3224

3225 3226
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
3227
			      frame,subframe,
3228 3229 3230
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
3231 3232
			      harq_pid,
			      NULL);
3233

3234
#ifdef LOCALIZATION
3235 3236
	    start_meas(&eNB->localization_stats);
	    aggregate_eNB_UE_localization_stats(eNB,
3237 3238 3239
						i,
						frame,
						subframe,
3240 3241
						get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
	    stop_meas(&eNB->localization_stats);
3242
#endif
3243 3244 3245
	    
	  } // mac_enabled==1
        } // Msg3_flag == 0
3246

3247
        // estimate timing advance for MAC
3248
        if (eNB->abstraction_flag == 0) {
3249
          sync_pos = lte_est_timing_advance_pusch(eNB,i);
3250
          eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
3251
        }
3252

3253 3254
#ifdef DEBUG_PHY_PROC
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
3255
              eNB->Mod_id,
3256 3257
              frame, subframe,
              i,
3258
              eNB->UE_stats[i].timing_advance_update);
3259
#endif
3260 3261


3262 3263 3264
      }  // ulsch not in error

      // process HARQ feedback
3265
#ifdef DEBUG_PHY_PROC
3266
      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
3267
            eNB->dlsch[i][0]->rnti,
3268 3269
            frame,subframe,
            i);
3270
#endif
3271
      process_HARQ_feedback(i,
3272
                            eNB,proc,
3273 3274 3275 3276 3277 3278 3279
                            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",
3280
            eNB->Mod_id,frame,subframe,
3281
            eNB->UE_stats[i].sector,
3282 3283 3284
            harq_pid,
            i,
            ret,
3285 3286 3287 3288 3289
            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]);
3290 3291 3292 3293
#endif
      
      // dump stats to VCD
      if (i==0) {
3294 3295 3296
	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]);
3297
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
3298 3299
	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
3300
      }
3301
    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
3302 3303


3304
    // update ULSCH statistics for tracing
3305
    if ((frame % 100 == 0) && (subframe == 4)) {
3306
      for (harq_idx=0; harq_idx<8; harq_idx++) {
3307 3308 3309 3310 3311 3312 3313 3314
        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]);
3315
          } else {
3316
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
3317 3318
          }

3319 3320 3321 3322
          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];
3323
        }
3324 3325
      }
    }
3326

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3327
    if ((frame % 100 == 0) && (subframe==4)) {
3328
      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
3329
					eNB->UE_stats[i].total_TBS_last);
3330

3331
      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
3332
    }
3333

3334
    // CBA (non-LTE)
3335
    cba_procedures(eNB,proc,i,harq_pid);
3336 3337
  } // loop i=0 ... NUMBER_OF_UE_MAX-1

3338
  if (eNB->abstraction_flag == 0) {
3339
    lte_eNB_I0_measurements(eNB,
3340 3341
			    subframe,
			    0,
3342 3343
			    eNB->first_run_I0_measurements);
    eNB->first_run_I0_measurements = 0;
3344
  }
3345

3346
#ifdef PHY_ABSTRACTION
3347 3348 3349 3350
  else {
    lte_eNB_I0_measurements_emul(eNB,
				 0);
  }
3351

3352
#endif
3353 3354


3355
  //}
3356 3357

#ifdef EMOS
3358
  phy_procedures_emos_eNB_RX(subframe,eNB);
3359 3360
#endif

Raymond Knopp's avatar
Raymond Knopp committed
3361
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
3362

3363
  stop_meas(&eNB->phy_proc_rx);
3364

3365 3366 3367 3368
}

#undef DEBUG_PHY_PROC

3369 3370 3371 3372
#ifdef Rel10
int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type)
{

3373
  int do_proc=0;// do nothing
3374 3375

  switch(r_type) {
3376
  case no_relay:
3377
    do_proc= no_relay; // perform the normal eNB operation
3378
    break;
3379

3380
  case multicast_relay:
3381
    if (((next_slot >>1) < 6) || ((next_slot >>1) > 8))
3382
      do_proc = 0; // do nothing
3383 3384 3385
    else // SF#6, SF#7 and SF#8
      do_proc = multicast_relay; // do PHY procedures eNB TX

3386
    break;
3387

3388 3389
  default: // should'not be here
    LOG_W(PHY,"Not supported relay type %d, do nothing\n", r_type);
3390
    do_proc=0;
3391 3392
    break;
  }
3393

3394 3395
  return do_proc;
}
3396
#endif