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 2674 2675
void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) {

  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


Raymond Knopp's avatar
Raymond Knopp committed
2719
void eNB_fep_full(PHY_VARS_eNB *eNB) {
2720

Raymond Knopp's avatar
Raymond Knopp committed
2721
  eNB_proc_t *proc = &eNB->proc;
2722
  int l;
2723
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2724

2725
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
2726
  start_meas(&eNB->ofdm_demod_stats);
2727 2728 2729 2730 2731 2732 2733
  remove_7_5_kHz(eNB,proc->subframe_rx<<1);
  remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1));
  for (l=0; l<fp->symbols_per_tti/2; l++) {
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		proc->subframe_rx<<1,
Raymond Knopp's avatar
Raymond Knopp committed
2734
		0,
2735 2736 2737 2738 2739 2740 2741 2742 2743 2744
		0
		);
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		1+(proc->subframe_rx<<1),
		0,
		0
		);
  }
2745
  stop_meas(&eNB->ofdm_demod_stats);
2746 2747 2748 2749 2750 2751
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
  
  if (eNB->node_function == NGFI_RRU_IF4p5) {
    /// **** send_IF4 of rxdataF to RCC (no prach now) **** ///
    send_IF4p5(eNB, proc->frame_rx, proc->subframe_rx, IF4p5_PULFFT, 0);
Raymond Knopp's avatar
Raymond Knopp committed
2752
  }    
2753 2754
}

Raymond Knopp's avatar
Raymond Knopp committed
2755
void eNB_fep_rru_if5(PHY_VARS_eNB *eNB) {
2756

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

}

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

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

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

}

void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){


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

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

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

Raymond Knopp's avatar
Raymond Knopp committed
2827

Raymond Knopp's avatar
Raymond Knopp committed
2828
  if (eNB->fep) eNB->fep(eNB);
2829

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

2833

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

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

2850

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

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

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

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

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

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



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

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

  // Do PUCCH processing first

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

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

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


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

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

2914

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

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


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

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

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

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

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

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

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

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

2987

2988
      start_meas(&eNB->ulsch_decoding_stats);
2989

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

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

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

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

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

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

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

3046
      }
3047

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

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

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

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

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

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

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

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

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

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

3110 3111 3112
            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
3113 3114 3115
            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));
3116 3117 3118
          }
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
3119

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

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

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

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

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



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


3324 3325 3326
      }  // ulsch not in error

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

3365

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

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

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

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

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

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

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

3414
#endif
3415 3416


3417
  //}
3418 3419

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

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

3425
  stop_meas(&eNB->phy_proc_rx);
3426

3427 3428 3429 3430
}

#undef DEBUG_PHY_PROC

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

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

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

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

3448
    break;
3449

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

3456 3457
  return do_proc;
}
3458
#endif