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

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

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

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

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

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

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

53 54
#include "T.h"

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

58 59
#include <time.h>

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

64

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

72 73 74 75 76 77
//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

78 79
void exit_fun(const char* s);

80 81
extern int exit_openair;

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

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

90
extern uint16_t hundred_times_log10_NPRB[100];
91

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

//DCI_ALLOC_t dci_alloc[8];

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

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

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

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

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

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

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

  return(0);
}
140

141

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

146 147

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

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

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

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

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

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

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

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

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

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

229 230 231
  return(-1);
}

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

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

246 247
  if ((harq_flag == openair_harq_DL) || (harq_flag == openair_harq_RA))  {// this is a DL request

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

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

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

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

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

286 287 288
  return(0);
}

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

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

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

}
#endif



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

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

317

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
331 332
#endif

333

334 335
}

Raymond Knopp's avatar
 
Raymond Knopp committed
336 337


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

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

  last_subframe_emos=0;

Raymond Knopp's avatar
 
Raymond Knopp committed
349

Raymond Knopp's avatar
 
Raymond Knopp committed
350

Raymond Knopp's avatar
 
Raymond Knopp committed
351

352
#ifdef EMOS_CHANNEL
353

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

365 366
#endif

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

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

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


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

Lionel Gauthier's avatar
Lionel Gauthier committed
399

Raymond Knopp's avatar
 
Raymond Knopp committed
400

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

Raymond Knopp's avatar
 
Raymond Knopp committed
404

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

Raymond Knopp's avatar
 
Raymond Knopp committed
407

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

414
  int subframe = proc->subframe_tx;
415

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

487
void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
488

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

495
  // generate Cell-Specific Reference Signals for both slots
496
  if (eNB->abstraction_flag==0) {
497 498 499 500 501 502 503 504 505 506 507 508 509 510
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
			 subframe<<1,0);
    // check that 2nd slot is for DL
    if (subframe_select(fp,subframe) == SF_DL)
      generate_pilots_slot(eNB,
			   txdataF,
			   AMP,
			   (subframe<<1)+1,0);
    
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0);
  }    
Raymond Knopp's avatar
 
Raymond Knopp committed
511

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

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

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

  }

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

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

}

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

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

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

    
    if (UE_id>=0) {
#if defined(SMBV) 
      // Configure this user
757 758
      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,
759 760 761 762 763 764 765 766 767 768 769 770
              dci_alloc->rnti,eNB->transmission_mode[(uint8_t)UE_id]);
	smbv_configure_user(smbv_fname,UE_id+1,eNB->transmission_mode[(uint8_t)UE_id],dci_alloc->rnti);
      }
      
#endif

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

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

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

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

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

889
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) {
890

891 892
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
893 894 895
  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;
896
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
897 898 899 900 901 902 903 904
  uint8_t *DLSCH_pdu=NULL;
  uint8_t DLSCH_pdu_tmp[768*8];
  uint8_t DLSCH_pdu_rar[256];
  int i;

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

921
#if defined(MESSAGE_CHART_GENERATOR_PHY)
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,
933 934 935 936
			   num_pdcch_symbols,
			   frame,
			   subframe,
			   dlsch_harq->mimo_mode==TM7?7:0),
937 938 939 940 941 942 943 944 945 946 947 948 949
		     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]++;
950

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

	int UE_id;

	if (crnti!=0) 
	  UE_id = add_ue(crnti,eNB);
	else 
	  UE_id = -1;
974
	    
975 976 977 978 979 980 981 982 983 984
	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;
985
	      
986 987 988 989 990
	  generate_eNB_ulsch_params_from_rar(DLSCH_pdu,
					     frame,
					     (subframe),
					     eNB->ulsch[(uint32_t)UE_id],
					     fp);
991
	      
992
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 1;
993
	      
994 995 996 997 998 999 1000 1001 1002 1003 1004
	  get_Msg3_alloc(fp,
			 subframe,
			 frame,
			 &eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
			 &eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
	  LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n",
		frame,
		subframe,
		UE_id,
		eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
		eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
Cedric Roux's avatar
Cedric Roux committed
1005

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

1015 1016 1017
          mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, (uint16_t)crnti,
                                       eNB->ulsch[UE_id]->Msg3_frame, eNB->ulsch[UE_id]->Msg3_subframe);

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

1034 1035 1036 1037 1038
    // 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);
    }
1039

1040
#endif
1041

1042

1043

1044 1045
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
1046
    LOG_T(PHY,"eNB DLSCH SDU: \n");
1047

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

1050 1051
    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);
1052 1053


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

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

1069
  if (eNB->abstraction_flag==0) {
1070

1071 1072 1073
    LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag);
    // 36-212
    start_meas(&eNB->dlsch_encoding_stats);
1074 1075 1076 1077 1078 1079 1080 1081
    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);
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
    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,
1093 1094 1095
			   num_pdcch_symbols,
			   frame,subframe,
			   0),
1096 1097 1098
		     0,
		     subframe<<1);
    stop_meas(&eNB->dlsch_scrambling_stats);
1099

1100 1101 1102
    start_meas(&eNB->dlsch_modulation_stats);


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


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

1124
#endif
1125
  dlsch->active = 0;
1126
}
1127

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

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

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

1156
#endif
1157

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

1160
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
1161
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
1162

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

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

1185
  }
1186 1187 1188


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

1196
  // clear the transmit data array for the current subframe
1197
  if (eNB->abstraction_flag==0) {
1198
    for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {      
1199
      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
1200 1201 1202
             0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
    }
  }
1203

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

1212
#if defined(SMBV) 
1213

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

1220
#endif
1221

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

1244
#endif
1245
  }
1246

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

1251 1252 1253
  if ((subframe_select(fp,ul_subframe)==SF_UL) ||
      (fp->frame_type == FDD)) {
    harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
1254

1255
    // clear DCI allocation maps for new subframe
1256
    for (i=0; i<NUMBER_OF_UE_MAX; i++)
1257 1258 1259
      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
1260 1261
      }
  }
1262

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

1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
  /* save old HARQ information needed for PHICH generation */
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    if (eNB->ulsch[i]) {
      /* Store first_rb and n_DMRS for correct PHICH generation below.
       * For PHICH generation we need "old" values of last scheduling
       * for this HARQ process. 'generate_eNB_dlsch_params' below will
       * overwrite first_rb and n_DMRS and 'generate_phich_top', done
       * after 'generate_eNB_dlsch_params', would use the "new" values
       * instead of the "old" ones.
       *
       * This has been tested for FDD only, may be wrong for TDD.
       *
       * TODO: maybe we should restructure the code to be sure it
       *       is done correctly. The main concern is if the code
       *       changes and first_rb and n_DMRS are modified before
       *       we reach here, then the PHICH processing will be wrong,
       *       using wrong first_rb and n_DMRS values to compute
       *       ngroup_PHICH and nseq_PHICH.
       *
       * TODO: check if that works with TDD.
       */
      if ((subframe_select(fp,ul_subframe)==SF_UL) ||
          (fp->frame_type == FDD)) {
        harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
        eNB->ulsch[i]->harq_processes[harq_pid]->previous_first_rb =
            eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
        eNB->ulsch[i]->harq_processes[harq_pid]->previous_n_DMRS =
            eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS;
      }
    }
  }

1301

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

1306
#if defined(SMBV) 
Raymond Knopp's avatar
 
Raymond Knopp committed
1307
  // Sets up PDCCH and DCI table
1308 1309
  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);
1310
    dump_dci(fp,&DCI_pdu->dci_alloc[0]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1311 1312
    smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
  }
1313 1314
#endif

1315 1316
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);

1317
  // loop over all DCIs for this subframe to generate DLSCH allocations
1318 1319 1320 1321 1322
  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);
1323
    dci_alloc = &DCI_pdu->dci_alloc[i];
1324

1325 1326 1327 1328
    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);
1329 1330
      else
	UE_id = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1331
    }
1332 1333
    else UE_id=0;
    
1334
    generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
1335

Raymond Knopp's avatar
 
Raymond Knopp committed
1336
  }
1337

1338 1339
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

Raymond Knopp's avatar
 
Raymond Knopp committed
1340
  // Apply physicalConfigDedicated if needed
1341 1342 1343 1344
  // 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
1345
  for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
Cedric Roux's avatar
Cedric Roux committed
1346 1347
    dci_alloc = &DCI_pdu->dci_alloc[i];

1348 1349 1350
    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);
1351 1352
      else
	UE_id = i;
1353
      
1354
      if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
1355
	LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
1356
	mac_xface->macphy_exit("FATAL\n"); 
1357
      }
1358
      generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1359
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1360
  }
1361

1362 1363


Lionel Gauthier's avatar
Lionel Gauthier committed
1364 1365


Raymond Knopp's avatar
 
Raymond Knopp committed
1366 1367
  // 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
1368

1369 1370

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

1375
  if (eNB->abstraction_flag == 0) {
1376

1377
    if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) {
1378
      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,
1379
            DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
1380 1381
    }

1382 1383 1384 1385 1386 1387

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1392
  }
1393

1394
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
Raymond Knopp's avatar
 
Raymond Knopp committed
1395
  else {
1396
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
1397
    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
1398
  }
1399

1400 1401
#endif

1402
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
1403

Raymond Knopp's avatar
 
Raymond Knopp committed
1404
  // Check for SI activity
1405

1406
  if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
1407

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

1410
#if defined(SMBV) 
1411

Raymond Knopp's avatar
 
Raymond Knopp committed
1412
    // Configures the data source of allocation (allocation is configured by DCI)
1413 1414
    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
1415 1416
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
    }
1417

1418
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1419
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1420

Raymond Knopp's avatar
 
Raymond Knopp committed
1421
  // Check for RA activity
1422
  if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
1423

1424
#if defined(SMBV) 
1425

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

1447
#if defined(FLEXRAN_AGENT_SB_IF)
1448 1449
#ifndef DISABLE_SF_TRIGGER
  //Send subframe trigger to the controller
1450
  if (mac_agent_registered[eNB->Mod_id]) {
1451
    agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
1452
  }
1453
#endif
1454 1455
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1456
  // Now scan UE specific DLSCH
1457
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
1458 1459 1460 1461
    {
      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)) {
1462

1463
	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);
1464 1465


Raymond Knopp's avatar
 
Raymond Knopp committed
1466
      }
Lionel Gauthier's avatar
Lionel Gauthier committed
1467

1468 1469 1470
      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)) {
1471

1472 1473
	// 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
1474
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1475
    }
1476

1477 1478


Raymond Knopp's avatar
 
Raymond Knopp committed
1479
  // if we have PHICH to generate
1480

1481
  if (is_phich_subframe(fp,subframe))
1482 1483 1484 1485
    {
      generate_phich_top(eNB,
			 proc,
			 AMP,
1486
			 0);
1487
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1488

1489 1490


1491
#ifdef EMOS
1492
  phy_procedures_emos_eNB_TX(subframe, eNB);
1493
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1494

1495
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
1496
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
1497
  
1498 1499
}

1500
void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid)
1501
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1502
  // this prepares the demodulation of the first PUSCH of a new user, containing Msg3
1503 1504
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1505

Raymond Knopp's avatar
 
Raymond Knopp committed
1506
  LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
1507
        eNB->Mod_id,
1508
        frame,subframe,
1509 1510 1511 1512
        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;
1513

1514 1515 1516
  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))   {
1517

1518
    //    harq_pid = 0;
1519

1520 1521 1522
    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
1523
    LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
1524
          eNB->Mod_id,
1525
          frame,subframe,UE_id);
1526 1527 1528 1529 1530 1531 1532 1533 1534
  }
}


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

1535
void process_HARQ_feedback(uint8_t UE_id,
1536
                           PHY_VARS_eNB *eNB,
1537
			   eNB_rxtx_proc_t *proc,
1538 1539 1540 1541 1542
                           uint8_t pusch_flag,
                           uint8_t *pucch_payload,
                           uint8_t pucch_sel,
                           uint8_t SR_payload)
{
1543

1544
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1545
  uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe;
1546 1547
  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];
1548
  LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
1549
  uint8_t subframe_m4,M,m;
1550 1551
  int mp;
  int all_ACKed=1,nb_alloc=0,nb_ACK=0;
1552 1553
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1554
  int harq_pid = subframe2harq_pid( fp,frame,subframe);
1555

1556 1557

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

1560 1561
    dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
    M=1;
1562

1563
    if (pusch_flag == 1) {
1564
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1565
      if (dlsch->subframe_tx[subframe_m4]==1)
1566 1567
	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);
1568 1569
    }
    else {
1570
      dlsch_ACK[0] = pucch_payload[0];
1571
      LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",eNB->Mod_id,
1572
	    frame,dlsch_ACK[0],subframe_m4);
kaltenbe's avatar
kaltenbe committed
1573
      /*
1574
	if (dlsch_ACK[0]==0)
1575
	AssertFatal(0,"Exiting on NAK on PUCCH\n");
kaltenbe's avatar
kaltenbe committed
1576
      */
1577
    }
1578

Lionel Gauthier's avatar
Lionel Gauthier committed
1579 1580 1581

#if defined(MESSAGE_CHART_GENERATOR_PHY)
    MSC_LOG_RX_MESSAGE(
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
		       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
1592
#endif
1593 1594
  } else { // TDD Handle M=1,2 cases only

1595
    M=ul_ACK_subframe2_M(fp,
1596 1597
                         subframe);

1598 1599 1600 1601 1602 1603 1604 1605
    // 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

1606
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1607
      dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling)
1608
	?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];
1609
    }
1610

1611
    else {  // PUCCH ACK/NAK
1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646
      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;
        }
1647
      }
1648
    }
1649 1650 1651 1652
  }

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

    for (m=0; m<M; m++) {
1656
      dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1657 1658
						 subframe,
						 m);
1659 1660 1661

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

1664 1665
    if (nb_alloc == nb_ACK)
      all_ACKed = 1;
1666
    else
1667
      all_ACKed = 0;
1668 1669 1670
  }


1671
  for (m=0,mp=-1; m<M; m++) {
1672

1673
    dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1674 1675
					       subframe,
					       m);
1676

1677 1678
    if (dlsch->subframe_tx[dl_subframe]==1) {
      if (pusch_flag == 1)
1679
        mp++;
1680
      else
1681
        mp = m;
1682

1683
      dl_harq_pid[m]     = dlsch->harq_ids[dl_subframe];
1684

1685
      if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
1686 1687 1688 1689
        if ((SR_payload == 1)&&(all_ACKed == 1))
          dlsch_ACK[m] = 1;
        else
          dlsch_ACK[m] = 0;
1690
      }
1691

1692
      if (dl_harq_pid[m]<dlsch->Mdlharq) {
1693 1694
        dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
1695
        LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id,
1696 1697 1698 1699 1700 1701 1702 1703 1704
              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");

1705
#endif
1706 1707 1708 1709 1710 1711 1712 1713

        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
1714
            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,
1715
                  dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
1716
#endif
1717

1718
            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),
1719
              T_INT(dl_harq_pid[m]));
1720

1721 1722 1723 1724 1725 1726 1727 1728 1729
            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++;

1730

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

1743 1744 1745 1746 1747 1748 1749
              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
1750
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
1751
                  dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
1752
#endif
1753

1754
            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),
1755
              T_INT(dl_harq_pid[m]));
1756

1757 1758 1759 1760 1761 1762 1763 1764
            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 +
1765
	      eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1766 1767
            /*
              ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
1768
              eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782
            */
          }

          // 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);
1783
#endif
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805

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


        }
1806
      }
1807
    }
1808 1809 1810
  }
}

1811
void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
1812
		      eNB_rxtx_proc_t *proc,
1813 1814 1815 1816 1817 1818
                      uint8_t UE_id,
                      int16_t *n1_pucch0,
                      int16_t *n1_pucch1,
                      int16_t *n1_pucch2,
                      int16_t *n1_pucch3)
{
1819

1820
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
1821
  uint8_t nCCE0,nCCE1;
1822
  int sf;
1823 1824
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1825 1826

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

1829 1830
    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];
1831
      *n1_pucch1 = -1;
1832
    } else {
1833 1834 1835
      *n1_pucch0 = -1;
      *n1_pucch1 = -1;
    }
1836
  } else {
1837

1838 1839 1840
    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
1841
        /*  if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
1842 1843 1844 1845 1846
	    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;*/
1847

1848 1849
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1850 1851 1852 1853 1854 1855 1856
          *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

1857 1858
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1859 1860 1861 1862 1863 1864 1865 1866 1867
          *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;
1868 1869
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1870 1871 1872 1873 1874 1875 1876
          *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;
1877 1878
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4];
1879 1880 1881 1882 1883 1884 1885
          *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",
1886
              eNB->Mod_id,
1887 1888 1889
              frame,
              subframe,frame_parms->tdd_config);
        return;
1890
      }
1891

1892
      break;
1893

1894 1895
    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)
1896 1897
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
1898 1899 1900 1901
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1902 1903
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1904 1905 1906 1907 1908
          *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",
1909
              eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7],eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]);
1910

1911 1912
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[8];
1913 1914 1915 1916 1917
          *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;

1918 1919
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7];
1920 1921 1922 1923 1924
          *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
1925 1926
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1927 1928 1929 1930
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1931 1932
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1933 1934 1935 1936 1937
          *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",
1938
              eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
1939
        return;
1940
      }
1941

1942
      break;
1943 1944
    }  // switch tdd_config

1945 1946 1947
    // Don't handle the case M>2
    *n1_pucch2 = -1;
    *n1_pucch3 = -1;
1948 1949 1950
  }
}

1951
void prach_procedures(PHY_VARS_eNB *eNB) {
1952

1953
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1954 1955 1956 1957
  uint16_t preamble_energy_list[64],preamble_delay_list[64];
  uint16_t preamble_max,preamble_energy_max;
  uint16_t i;
  int8_t UE_id;
1958 1959
  int subframe = eNB->proc.subframe_prach;
  int frame = eNB->proc.frame_prach;
1960
  uint8_t CC_id = eNB->CC_id;
1961

1962
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
1963 1964
  memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
  memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
1965

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

1970

1971
    rx_prach(eNB,
1972 1973 1974 1975 1976 1977 1978
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
  } else {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {

1979
      LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
1980
            UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
1981
            PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
1982
            fp->prach_config_common.rootSequenceIndex,
1983 1984
            PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex);

Raymond Knopp's avatar
 
Raymond Knopp committed
1985
      if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) &&
1986
          (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex ==
1987
           fp->prach_config_common.rootSequenceIndex) ) {
1988 1989 1990
        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;

1991
      }
1992
    }
1993
  }
1994

1995 1996 1997
  preamble_energy_max = preamble_energy_list[0];
  preamble_max = 0;

1998
  for (i=1; i<64; i++) {
1999 2000 2001 2002
    if (preamble_energy_max < preamble_energy_list[i]) {
      preamble_energy_max = preamble_energy_list[i];
      preamble_max = i;
    }
2003 2004 2005
  }

#ifdef DEBUG_PHY_PROC
2006
  LOG_D(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
2007 2008 2009
        preamble_max,
        preamble_energy_list[preamble_max],
        preamble_delay_list[preamble_max]);
2010 2011
#endif

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

2014
    UE_id = find_next_ue_index(eNB);
2015
 
2016
    if (UE_id>=0) {
2017
      eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
2018

2019
      eNB->UE_stats[(uint32_t)UE_id].sector = 0;
2020
      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",
2021 2022
            eNB->Mod_id,
            eNB->CC_id,
2023 2024
            frame,
            subframe,
2025
	    UE_id,
2026 2027 2028 2029
            preamble_max,
            preamble_energy_max/10,
            preamble_energy_max%10,
            preamble_delay_list[preamble_max]);
2030

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

2034
      if (eNB->mac_enabled==1) {
2035 2036
        uint8_t update_TA=4;

2037
        switch (fp->N_RB_DL) {
2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054
        case 6:
          update_TA = 16;
          break;

        case 25:
          update_TA = 4;
          break;

        case 50:
          update_TA = 2;
          break;

        case 100:
          update_TA = 1;
          break;
        }

2055 2056 2057 2058 2059 2060
	mac_xface->initiate_ra_proc(eNB->Mod_id,
				    eNB->CC_id,
				    frame,
				    preamble_max,
				    preamble_delay_list[preamble_max]*update_TA,
				    0,subframe,0);
2061 2062
      }      

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

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

2085 2086
  if ((eNB->dlsch[UE_id][0]) &&
      (eNB->dlsch[UE_id][0]->rnti>0) &&
Cedric Roux's avatar
Cedric Roux committed
2087
      (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) {
2088

2089
    // check SR availability
2090 2091
    do_SR = is_SR_subframe(eNB,proc,UE_id);
    //      do_SR = 0;
Cedric Roux's avatar
Cedric Roux committed
2092

2093 2094
    // Now ACK/NAK
    // First check subframe_tx flag for earlier subframes
2095

2096
    get_n1_pucch_eNB(eNB,
Cedric Roux's avatar
Cedric Roux committed
2097 2098 2099 2100 2101 2102 2103
                     proc,
                     UE_id,
                     &n1_pucch0,
                     &n1_pucch1,
                     &n1_pucch2,
                     &n1_pucch3);

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

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

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

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


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

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

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

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

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

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

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

2239
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2240 2241 2242 2243 2244
        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);
2245 2246
#endif

Cedric Roux's avatar
Cedric Roux committed
2247 2248 2249 2250 2251 2252 2253
        process_HARQ_feedback(UE_id,eNB,proc,
                            0,// pusch_flag
                            pucch_payload0,
                            2,
                            SR_payload);
      } // FDD
      else {  //TDD
2254

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

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

Cedric Roux's avatar
Cedric Roux committed
2259 2260 2261 2262 2263 2264 2265
        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;
        }
2266

Cedric Roux's avatar
Cedric Roux committed
2267 2268
        // if SR was detected, use the n1_pucch from SR
        if (SR_payload==1) {
2269
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2270 2271 2272 2273
          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);
2274
#endif
2275

Cedric Roux's avatar
Cedric Roux committed
2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287
          if (eNB->abstraction_flag == 0)
            metric0 = rx_pucch(eNB,
                               format,
                               UE_id,
                               eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
                               0, //n2_pucch
                               0, // shortened format
                               pucch_payload0,
                               frame,
                               subframe,
                               PUCCH1a_THRES);
          else {
2288
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2289 2290 2291 2292 2293
            metric0 = rx_pucch_emul(eNB,proc,
                                    UE_id,
                                    format,
                                    0,
                                    pucch_payload0);
2294
#endif
Cedric Roux's avatar
Cedric Roux committed
2295 2296
          }
        } else { //using n1_pucch0/n1_pucch1 resources
2297
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2298 2299 2300 2301
          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);
2302
#endif
Cedric Roux's avatar
Cedric Roux committed
2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319
          metric0=0;
          metric1=0;

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

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

Cedric Roux's avatar
Cedric Roux committed
2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372
        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
        }
2373

2374
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2375 2376 2377 2378
        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]);
2379
#endif
Cedric Roux's avatar
Cedric Roux committed
2380 2381 2382 2383 2384 2385
        process_HARQ_feedback(UE_id,eNB,proc,
                              0,// pusch_flag
                              pucch_payload,
                              pucch_sel,
                              SR_payload);
      } // TDD
2386
    }
Cedric Roux's avatar
Cedric Roux committed
2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409

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

      if (eNB->first_sr[UE_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
        eNB->first_sr[UE_id] = 0;
        eNB->dlsch[UE_id][0]->harq_processes[0]->round=0;
        eNB->dlsch[UE_id][0]->harq_processes[0]->status=SCH_IDLE;
        LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d First SR\n",
              eNB->Mod_id,
              eNB->ulsch[UE_id]->rnti,frame,subframe);
      }

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

2412

2413
void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
2414

2415 2416
  uint8_t access_mode;
  int num_active_cba_groups;
2417 2418
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2419 2420
  uint16_t rnti=0;
  int ret=0;
2421
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2422

2423 2424
  if (eNB->ulsch[UE_id]==NULL) return;

2425
  num_active_cba_groups = eNB->ulsch[UE_id]->num_active_cba_groups;
2426 2427
 
  if ((num_active_cba_groups > 0) &&
2428 2429
      (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)) {
2430 2431 2432 2433
    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",
2434
	  eNB->Mod_id,harq_pid,
2435
	  frame,subframe,
2436
	  UE_id, (uint16_t)eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->UE_stats[UE_id].mode]);
2437 2438
#endif
    
2439
    if (eNB->abstraction_flag==0) {
2440
      rx_ulsch(eNB,proc,
2441
	       eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2442
	       UE_id,
2443
	       eNB->ulsch,
2444 2445 2446 2447 2448
	       0);
    }
    
#ifdef PHY_ABSTRACTION
    else {
2449
      rx_ulsch_emul(eNB,proc,
2450
		    eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2451
		    UE_id);
2452 2453 2454 2455
    }
    
#endif
    
2456
    if (eNB->abstraction_flag == 0) {
2457
      ret = ulsch_decoding(eNB,proc,
2458 2459
			   UE_id,
			   0, // control_only_flag
2460 2461
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->V_UL_DAI,
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2462 2463 2464 2465
    }
    
#ifdef PHY_ABSTRACTION
    else {
2466
      ret = ulsch_decoding_emul(eNB,
2467
				proc,
2468 2469 2470 2471 2472 2473
				UE_id,
				&rnti);
    }
    
#endif
    
2474
    if (eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2475 2476
#ifdef DEBUG_PHY_PROC
      
2477
      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);
2478 2479
#endif
      access_mode = UNKNOWN_ACCESS;
2480 2481 2482
      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],
2483
		  fp->N_RB_DL,
2484
		  &rnti, &access_mode);
2485
      eNB->UE_stats[UE_id].rank = eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_RI[0];
2486 2487
    }
    
2488 2489
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0;
    eNB->ulsch[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE;
2490
      
2491 2492 2493 2494
    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)) {
2495
#ifdef DEBUG_PHY_PROC
2496 2497 2498
      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);
2499
#endif
2500 2501 2502 2503
      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;
    }
2504

2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519
    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;
2520 2521
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539
      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
2540 2541
	if ((eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) && 
	    (eNB->mac_enabled==1)) {
2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569
	  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
2570
  }
2571

2572
}
2573

2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584
typedef struct {
  PHY_VARS_eNB *eNB;
  int slot;
} fep_task;

void fep0(PHY_VARS_eNB *eNB,int slot) {

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

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

2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
  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
		);
  }
}



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
2608

2609 2610 2611
    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
2612 2613 2614 2615

    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" );
2616
      return NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2617
    }
2618
  }
Raymond Knopp's avatar
Raymond Knopp committed
2619 2620 2621



2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635
  return(NULL);
}

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

  eNB_proc_t *proc = &eNB->proc;

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

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

Raymond Knopp's avatar
Raymond Knopp committed
2636

2637 2638
}

2639 2640 2641
extern void *td_thread(void*);

void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
2642 2643 2644

  eNB_proc_t *proc = &eNB->proc;

2645 2646
  proc->tdp.eNB = eNB;
  proc->instance_cnt_td         = -1;
2647
    
2648 2649
  pthread_mutex_init( &proc->mutex_td, NULL);
  pthread_cond_init( &proc->cond_td, NULL);
2650

2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668
  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);
2669 2670 2671

}

Raymond Knopp's avatar
Raymond Knopp committed
2672

2673
void eNB_fep_full_2thread(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2674 2675

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

2677
  struct timespec wait;
2678

2679 2680 2681 2682 2683 2684 2685
  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) {
2686
    printf("[eNB] ERROR pthread_mutex_lock for fep thread (IC %d)\n", proc->instance_cnt_fep);
2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699
    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;

2700

2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711
  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
2712
  wait_on_busy_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread");  
2713 2714

  stop_meas(&eNB->ofdm_demod_stats);
2715 2716
}

Raymond Knopp's avatar
Raymond Knopp committed
2717 2718


2719
void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2720

2721
  int l;
2722
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2723

2724
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
2725
  start_meas(&eNB->ofdm_demod_stats);
2726 2727
  remove_7_5_kHz(eNB,proc_rxtx->subframe_rx<<1);
  remove_7_5_kHz(eNB,1+(proc_rxtx->subframe_rx<<1));
2728 2729 2730 2731
  for (l=0; l<fp->symbols_per_tti/2; l++) {
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
2732
		(proc_rxtx->subframe_rx)<<1,
Raymond Knopp's avatar
Raymond Knopp committed
2733
		0,
2734 2735 2736 2737 2738
		0
		);
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
2739
		1+((proc_rxtx->subframe_rx)<<1),
2740 2741 2742 2743
		0,
		0
		);
  }
2744
  stop_meas(&eNB->ofdm_demod_stats);
2745 2746 2747 2748 2749
  
  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) **** ///
2750
    send_IF4p5(eNB, proc_rxtx->frame_rx, proc_rxtx->subframe_rx, IF4p5_PULFFT, 0);
Raymond Knopp's avatar
Raymond Knopp committed
2751
  }    
2752 2753
}

2754
void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
2755

Raymond Knopp's avatar
Raymond Knopp committed
2756
  eNB_proc_t *proc=&eNB->proc;
2757 2758 2759 2760 2761 2762 2763 2764 2765
  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 );          

}

2766
void do_prach(PHY_VARS_eNB *eNB,int frame,int subframe) {
2767

Raymond Knopp's avatar
Raymond Knopp committed
2768
  eNB_proc_t *proc = &eNB->proc;
2769 2770 2771
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;

  // check if we have to detect PRACH first
2772
  if (is_prach_subframe(fp,frame,subframe)>0) { 
2773 2774 2775
    /* accept some delay in processing - up to 5ms */
    int i;
    for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) {
2776
      LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", frame,subframe,proc->instance_cnt_prach);
2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792
      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
2793 2794
    proc->frame_prach = frame;
    proc->subframe_prach = subframe;
2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807
    
    // 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 );
  }

}

2808
void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc){
2809 2810


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

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

Raymond Knopp's avatar
Raymond Knopp committed
2819 2820 2821
  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 );
2822
  
2823
  start_meas(&eNB->phy_proc_rx);
2824
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe);
2825

Raymond Knopp's avatar
Raymond Knopp committed
2826

2827
  if (eNB->fep) eNB->fep(eNB,proc);
2828

Raymond Knopp's avatar
Raymond Knopp committed
2829
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 0 );
2830 2831
}

2832

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

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

2849

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

Raymond Knopp's avatar
Raymond Knopp committed
2852
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
2853

2854
#ifdef DEBUG_PHY_PROC
2855
  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
2856
#endif
2857

2858
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
2859

2860
  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
2861
    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
2862
             eNB->frame_parms.samples_per_tti * 4));
2863

2864 2865 2866 2867
  eNB->rb_mask_ul[0]=0;
  eNB->rb_mask_ul[1]=0;
  eNB->rb_mask_ul[2]=0;
  eNB->rb_mask_ul[3]=0;
2868 2869 2870



2871
  // Check for active processes in current subframe
2872
  harq_pid = subframe2harq_pid(fp,
2873 2874 2875 2876
                               frame,subframe);

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

  // Do PUCCH processing first

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2883
    pucch_procedures(eNB,proc,i,harq_pid);
2884
  }
2885

2886
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2887

2888
    // check for Msg3
2889
    if (eNB->mac_enabled==1) {
2890
      if (eNB->UE_stats[i].mode == RA_RESPONSE) {
2891
	process_Msg3(eNB,proc,i,harq_pid);
2892 2893
      }
    }
2894 2895


2896 2897 2898
    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;
2899

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

2913

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

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


2932
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
2933

2934
      eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
2935
				    nPRS)%12;
2936

2937
      if (fp->frame_type == FDD ) {
2938
        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
2939

2940 2941
        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
2942
        } else {
2943
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
2944
        }
2945
      }
2946

2947 2948
      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",
2949
            eNB->Mod_id,harq_pid,frame,subframe,
2950 2951 2952 2953 2954 2955 2956 2957 2958 2959
            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,
2960
            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
2961
            nPRS,
2962 2963 2964 2965
            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;
2966
      start_meas(&eNB->ulsch_demodulation_stats);
2967

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

2976 2977
#ifdef PHY_ABSTRACTION
      else {
2978
        rx_ulsch_emul(eNB,proc,
2979
                      eNB->UE_stats[i].sector,  // this is the effective sector id
2980 2981
                      i);
      }
2982

2983
#endif
2984
      stop_meas(&eNB->ulsch_demodulation_stats);
2985

2986

2987
      start_meas(&eNB->ulsch_decoding_stats);
2988

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

2997 2998
#ifdef PHY_ABSTRACTION
      else {
2999 3000
        ret = ulsch_decoding_emul(eNB,
				  proc,
3001 3002 3003
                                  i,
                                  &rnti);
      }
3004

3005
#endif
3006
      stop_meas(&eNB->ulsch_decoding_stats);
3007

3008
      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",
3009
            eNB->Mod_id,harq_pid,
3010
            frame,subframe,
3011 3012 3013 3014 3015 3016 3017 3018 3019
            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],
3020
            ret);
3021

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

3026
      eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
3027 3028
#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",
3029
            eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
3030
#endif
3031
      eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
3032

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

3045
      }
3046

3047
      if (eNB->ulsch[i]->Msg3_flag == 1)
3048
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
3049

3050
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
3051
        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),
3052
          T_INT(harq_pid));
3053

3054 3055 3056 3057
        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++;
3058

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

3061
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3062
          LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
3063 3064
                eNB->Mod_id,
                eNB->CC_id,
3065
                frame,subframe, i,
3066
                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
3067
                fp->maxHARQ_Msg3Tx-1);
3068 3069

	  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",
3070
		eNB->Mod_id,harq_pid,
3071
		frame,subframe,
3072 3073 3074 3075 3076 3077 3078 3079 3080
		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],
3081 3082
		ret);

3083
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round ==
3084
              fp->maxHARQ_Msg3Tx) {
3085
            LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n",
3086
                  eNB->Mod_id, i);
3087
            eNB->UE_stats[i].mode = PRACH;
3088 3089 3090
	    if (eNB->mac_enabled==1) {
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3091
					frame,
3092
					eNB->UE_stats[i].crnti);
3093
	    }
3094
            mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
3095

3096 3097
            eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
            //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0;
3098

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

3103
            get_Msg3_alloc_ret(fp,
3104
                               subframe,
3105
                               frame,
3106 3107
                               &eNB->ulsch[i]->Msg3_frame,
                               &eNB->ulsch[i]->Msg3_subframe);
Cedric Roux's avatar
Cedric Roux committed
3108

3109 3110 3111
            mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, eNB->ulsch[i]->rnti,
                                         eNB->ulsch[i]->Msg3_frame, eNB->ulsch[i]->Msg3_subframe);

Cedric Roux's avatar
Cedric Roux committed
3112 3113 3114
            T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
              T_INT(i), T_INT(eNB->ulsch[i]->rnti), T_INT(0 /* 0 is for retransmission*/),
              T_INT(eNB->ulsch[i]->Msg3_frame), T_INT(eNB->ulsch[i]->Msg3_subframe));
3115 3116 3117
          }
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
3118

3119 3120
        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",
3121
                eNB->Mod_id,harq_pid,
3122
                frame,subframe, i,
3123 3124 3125 3126
                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]);
3127 3128 3129

#if defined(MESSAGE_CHART_GENERATOR_PHY)
          MSC_LOG_RX_DISCARDED_MESSAGE(
3130 3131 3132 3133 3134 3135 3136
				       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
				       );
3137
#endif
3138

3139
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) {
3140
            LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
3141
                  eNB->Mod_id,harq_pid,
3142
                  frame,subframe, i,
3143
                  eNB->ulsch[i]->Mlimit);
3144

3145 3146 3147 3148
            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++;
3149 3150

	    // indicate error to MAC
3151 3152 3153 3154 3155 3156 3157 3158 3159
	    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);
3160 3161 3162 3163
          }
        }
      }  // ulsch in error
      else {
3164 3165 3166



3167
        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),
3168 3169
          T_INT(harq_pid));

3170
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3171
	  LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
3172
		eNB->Mod_id,harq_pid,
3173 3174
		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",
3175
		eNB->Mod_id,harq_pid,
3176
		frame,subframe,
3177 3178 3179 3180 3181 3182 3183 3184 3185
		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],
3186 3187 3188 3189
		ret);
	}
#if defined(MESSAGE_CHART_GENERATOR_PHY)
        MSC_LOG_RX_MESSAGE(
3190 3191 3192 3193 3194 3195
			   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
			   );
3196
#endif
3197
        for (j=0; j<fp->nb_antennas_rx; j++)
3198
          //this is the RSSI per RB
3199
          eNB->UE_stats[i].UL_rssi[j] =
3200
	    
3201 3202
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
                     (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
3203
                     fp->ofdm_symbol_size) -
3204 3205
            eNB->rx_total_gain_dB -
            hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
3206
            get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
3207
	    
3208 3209 3210 3211
        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;
3212

3213
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3214
	  if (eNB->mac_enabled==1) {
3215

3216
	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
3217
		  eNB->Mod_id,
3218
		  frame,harq_pid,i);
3219 3220 3221 3222 3223 3224 3225 3226 3227
	    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);
3228 3229
	    
	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
3230 3231
	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	      eNB->UE_stats[i].mode = PRACH;
3232 3233
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3234
					frame,
3235 3236 3237
					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;
3238 3239 3240
	    } // Msg3_flag == 0
	    
	  } // mac_enabled==1
3241

3242 3243
          eNB->UE_stats[i].mode = PUSCH;
          eNB->ulsch[i]->Msg3_flag = 0;
3244

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

3247
          for (k=0; k<8; k++) { //harq_processes
3248 3249 3250 3251
            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;
3252
            }
3253

3254 3255 3256
            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;
3257

3258 3259 3260 3261 3262
            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;
3263
            }
3264 3265
          }

3266 3267 3268
          eNB->UE_stats[i].dlsch_sliding_cnt=0;
          eNB->UE_stats[i].dlsch_NAK_round0=0;
          eNB->UE_stats[i].dlsch_mcs_offset=0;
3269 3270 3271
        } // Msg3_flag==1
	else {  // Msg3_flag == 0

3272
#ifdef DEBUG_PHY_PROC
3273 3274
#ifdef DEBUG_ULSCH
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
3275
                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
3276

3277 3278
          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]);
3279 3280 3281

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

3284
	  if (eNB->mac_enabled==1) {
3285

3286 3287
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
3288
			      frame,subframe,
3289 3290 3291
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
3292 3293
			      harq_pid,
			      NULL);
3294

3295
#ifdef LOCALIZATION
3296 3297
	    start_meas(&eNB->localization_stats);
	    aggregate_eNB_UE_localization_stats(eNB,
3298 3299 3300
						i,
						frame,
						subframe,
3301 3302
						get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
	    stop_meas(&eNB->localization_stats);
3303
#endif
3304 3305 3306
	    
	  } // mac_enabled==1
        } // Msg3_flag == 0
3307

3308
        // estimate timing advance for MAC
3309
        if (eNB->abstraction_flag == 0) {
3310
          sync_pos = lte_est_timing_advance_pusch(eNB,i);
3311
          eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
3312
        }
3313

3314 3315
#ifdef DEBUG_PHY_PROC
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
3316
              eNB->Mod_id,
3317 3318
              frame, subframe,
              i,
3319
              eNB->UE_stats[i].timing_advance_update);
3320
#endif
3321 3322


3323 3324 3325
      }  // ulsch not in error

      // process HARQ feedback
3326
#ifdef DEBUG_PHY_PROC
3327
      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
3328
            eNB->dlsch[i][0]->rnti,
3329 3330
            frame,subframe,
            i);
3331
#endif
3332
      process_HARQ_feedback(i,
3333
                            eNB,proc,
3334 3335 3336 3337 3338 3339 3340
                            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",
3341
            eNB->Mod_id,frame,subframe,
3342
            eNB->UE_stats[i].sector,
3343 3344 3345
            harq_pid,
            i,
            ret,
3346 3347 3348 3349 3350
            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]);
3351 3352 3353 3354
#endif
      
      // dump stats to VCD
      if (i==0) {
3355 3356 3357
	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]);
3358
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
3359 3360
	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
3361
      }
3362
    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
3363

3364

3365
    // update ULSCH statistics for tracing
3366
    if ((frame % 100 == 0) && (subframe == 4)) {
3367
      for (harq_idx=0; harq_idx<8; harq_idx++) {
3368 3369 3370 3371 3372 3373 3374 3375
        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]);
3376
          } else {
3377
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
3378 3379
          }

3380 3381 3382 3383
          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];
3384
        }
3385 3386
      }
    }
3387

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3388
    if ((frame % 100 == 0) && (subframe==4)) {
3389
      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
3390
					eNB->UE_stats[i].total_TBS_last);
3391

3392
      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
3393
    }
3394

3395
    // CBA (non-LTE)
3396
    cba_procedures(eNB,proc,i,harq_pid);
3397 3398
  } // loop i=0 ... NUMBER_OF_UE_MAX-1

3399
  if (eNB->abstraction_flag == 0) {
3400
    lte_eNB_I0_measurements(eNB,
3401 3402
			    subframe,
			    0,
3403 3404
			    eNB->first_run_I0_measurements);
    eNB->first_run_I0_measurements = 0;
3405
  }
3406

3407
#ifdef PHY_ABSTRACTION
3408 3409 3410 3411
  else {
    lte_eNB_I0_measurements_emul(eNB,
				 0);
  }
3412

3413
#endif
3414 3415


3416
  //}
3417 3418

#ifdef EMOS
3419
  phy_procedures_emos_eNB_RX(subframe,eNB);
3420 3421
#endif

Raymond Knopp's avatar
Raymond Knopp committed
3422
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
3423

3424
  stop_meas(&eNB->phy_proc_rx);
3425

3426 3427 3428 3429
}

#undef DEBUG_PHY_PROC

3430 3431 3432 3433
#ifdef Rel10
int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type)
{

3434
  int do_proc=0;// do nothing
3435 3436

  switch(r_type) {
3437
  case no_relay:
3438
    do_proc= no_relay; // perform the normal eNB operation
3439
    break;
3440

3441
  case multicast_relay:
3442
    if (((next_slot >>1) < 6) || ((next_slot >>1) > 8))
3443
      do_proc = 0; // do nothing
3444 3445 3446
    else // SF#6, SF#7 and SF#8
      do_proc = multicast_relay; // do PHY procedures eNB TX

3447
    break;
3448

3449 3450
  default: // should'not be here
    LOG_W(PHY,"Not supported relay type %d, do nothing\n", r_type);
3451
    do_proc=0;
3452 3453
    break;
  }
3454

3455 3456
  return do_proc;
}
3457
#endif