phy_procedures_lte_eNb.c 113 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * 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
 */

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
25 26 27
 * \date 2011
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr
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 66 67 68 69
//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

70 71
void exit_fun(const char* s);

72 73
extern int exit_openair;

74 75
// Fix per CC openair rf/if device update
// extern openair0_device openair0;
76

77 78 79
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)));
80 81
int *eNB_sync_buffer[2] = {eNB_sync_buffer0, eNB_sync_buffer1};

82
extern uint16_t hundred_times_log10_NPRB[100];
83

84
unsigned int max_peak_val;
85
int max_sync_pos;
86 87 88 89 90 91 92

//DCI_ALLOC_t dci_alloc[8];

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

93
#if defined(SMBV) 
94 95
extern const char smbv_fname[];
extern unsigned short config_frames[4];
96
extern uint8_t smbv_frame_cnt;
97 98 99 100 101 102
#endif

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

103
uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id)
104
{
Raymond Knopp's avatar
 
Raymond Knopp committed
105

106 107
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
108

109
  LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking for SR TXOp(sr_ConfigIndex %d)\n",
110 111
        eNB->Mod_id,eNB->ulsch[UE_id]->rnti,frame,subframe,
        eNB->scheduling_request_config[UE_id].sr_ConfigIndex);
112

113 114
  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)
115
      return(1);
116 117
  } 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))
118
      return(1);
119 120
  } 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))
121
      return(1);
122 123
  } 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))
124
      return(1);
125 126
  } 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))
127
      return(1);
128 129 130 131
  }

  return(0);
}
132

133

134
int32_t add_ue(int16_t rnti, PHY_VARS_eNB *eNB)
135
{
136
  uint8_t i;
137

138 139

  LOG_D(PHY,"[eNB %d/%d] Adding UE with rnti %x\n",
140 141
        eNB->Mod_id,
        eNB->CC_id,
142
        (uint16_t)rnti);
143 144

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

157 158 159
	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));
160
	LOG_D(PHY,"Initializing Po_PUCCH: p0_NominalPUCCH %d, gain %d => %d\n",
161 162 163
	      eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH,
	      eNB->rx_total_gain_dB,
	      eNB->UE_stats[i].Po_PUCCH);
164
  
165
        return(i);
166
      }
167
    }
168 169 170 171
  }
  return(-1);
}

172
int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) {
173
  uint8_t i;
174
  int CC_id;
175
  PHY_VARS_eNB *eNB;
176 177

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
178
    eNB = PHY_vars_eNB_g[Mod_idP][CC_id];
179
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
180
      if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) {
181 182 183 184
	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 {
185
	if (eNB->UE_stats[i].crnti==rntiP) {
186
	  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Removed ue %"PRIx16" ", rntiP);
187 188 189

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

190
	  //LOG_D(PHY,("[PHY] UE_id %d\n",i);
191 192 193 194
	  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));
195 196
	  //  mac_exit_wrapper("Removing UE");
	  
197

198 199
	  return(i);
	}
200
      }
201
    }
202
  }
203
  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (not found)", rntiP);
204 205 206
  return(-1);
}

207
int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
208
{
209
  uint8_t i;
210

211
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
212 213
    if (eNB->UE_stats[i].crnti==0) {
      /*if ((eNB->dlsch[i]) &&
214 215
	(eNB->dlsch[i][0]) &&
	(eNB->dlsch[i][0]->rnti==0))*/
216 217 218
      LOG_D(PHY,"Next free UE id is %d\n",i);
      return(i);
    }
219
  }
220

221 222 223
  return(-1);
}

Lionel Gauthier's avatar
Lionel Gauthier committed
224
int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t ul_flag)
225 226 227 228
{
  LTE_eNB_DLSCH_t *DLSCH_ptr;
  LTE_eNB_ULSCH_t *ULSCH_ptr;
  uint8_t ulsch_subframe,ulsch_frame;
229
  int i;
Raymond Knopp's avatar
 
Raymond Knopp committed
230
  int8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]);
231 232

  if (UE_id==-1) {
233
    LOG_D(PHY,"Cannot find UE with rnti %x (Mod_id %d, CC_id %d)\n",rnti, Mod_id, CC_id);
234 235
    *round=0;
    return(-1);
236 237 238
  }

  if (ul_flag == 0)  {// this is a DL request
239
    DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[(uint32_t)UE_id][0];
240

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

244 245 246 247 248
    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;
249
      *round = 0;
250 251 252
    } else {
      printf("%s:%d: bad state for harq process - PLEASE REPORT!!\n", __FILE__, __LINE__);
      abort();
253
    }
254
  } else { // This is a UL request
255

256 257 258
    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);
259
    // Note this is for TDD configuration 3,4,5 only
260
    *harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,
261 262
                                  ulsch_frame,
                                  ulsch_subframe);
263
    *round    = ULSCH_ptr->harq_processes[*harq_pid]->round;
264
    LOG_T(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Checking HARQ, round %d\n",Mod_id,*harq_pid,frame,subframe,*round);
265
  }
266

267 268 269
  return(0);
}

270
int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
271
{
272
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
273 274
}

275 276
int16_t get_target_pucch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
{
277
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
278 279
}

280
#ifdef EMOS
281
void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB)
282
{
283 284 285 286

}
#endif

287

288

289
void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type)
290 291
{
  UNUSED(r_type);
292
  int subframe = proc->subframe_rx;
293

294
#ifdef DEBUG_PHY_PROC
295
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", eNB->Mod_id,proc->frame_rx, subframe);
296
#endif
297

298

299
  if (eNB->abstraction_flag == 0) {
300
    lte_eNB_I0_measurements(eNB,
301
			    subframe,
302
                            0,
303
                            eNB->first_run_I0_measurements);
Raymond Knopp's avatar
 
Raymond Knopp committed
304
  }
305

306
#ifdef PHY_ABSTRACTION
Raymond Knopp's avatar
 
Raymond Knopp committed
307
  else {
308
    lte_eNB_I0_measurements_emul(eNB,
309
                                 0);
310
  }
311

Raymond Knopp's avatar
 
Raymond Knopp committed
312 313
#endif

314

315 316
}

Raymond Knopp's avatar
 
Raymond Knopp committed
317 318


319
#ifdef EMOS
320
void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *eNB)
321 322
{

323 324
  uint8_t aa;
  uint16_t last_subframe_emos;
325
  uint16_t pilot_pos1 = 3 - eNB->frame_parms.Ncp, pilot_pos2 = 10 - 2*eNB->frame_parms.Ncp;
326
  uint32_t bytes;
327 328 329

  last_subframe_emos=0;

Raymond Knopp's avatar
 
Raymond Knopp committed
330

Raymond Knopp's avatar
 
Raymond Knopp committed
331

Raymond Knopp's avatar
 
Raymond Knopp committed
332

333
#ifdef EMOS_CHANNEL
334

335
  //if (last_slot%2==1) // this is for all UL subframes
336
  if (subframe==3)
337 338 339 340 341 342 343
    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));
344
    }
345

346 347
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
348
  if (subframe==4) {
349
    emos_dump_eNB.timestamp = rt_get_time_ns();
350 351 352 353 354
    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],
355
           sizeof(PHY_MEASUREMENTS_eNB));
356
    memcpy(&emos_dump_eNB.UE_stats[0],&eNB->UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats));
357 358

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

360 361
    //bytes = rtf_put(CHANSOUNDER_FIFO_MINOR, "test", sizeof("test"));
    if (bytes!=sizeof(fifo_dump_emos_eNB)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
362
      LOG_W(PHY,"[eNB %d] Frame %d, subframe %d, Problem writing EMOS data to FIFO (bytes=%d, size=%d)\n",
363
            eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, subframe,bytes,sizeof(fifo_dump_emos_eNB));
364
    } else {
365
      if (eNB->proc[(subframe+1)%10].frame_tx%100==0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
366
        LOG_I(PHY,"[eNB %d] Frame %d (%d), subframe %d, Writing %d bytes EMOS data to FIFO\n",
367
              eNB->Mod_id,eNB->proc[(subframe+1)%10].frame_rx, ((fifo_dump_emos_eNB*)&emos_dump_eNB)->frame_tx, subframe, bytes);
368
      }
369
    }
370 371 372 373 374 375 376
  }
}
#endif


#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
#define AMP_OVER_2 (AMP>>1)
377 378
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)};
379

Lionel Gauthier's avatar
Lionel Gauthier committed
380

Raymond Knopp's avatar
 
Raymond Knopp committed
381

Cedric Roux's avatar
Cedric Roux committed
382
unsigned int taus(void);
383
DCI_PDU DCI_pdu_tmp;
Raymond Knopp's avatar
 
Raymond Knopp committed
384

385

386
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,relaying_type_t r_type) {
387 388


389
#ifdef Rel10
390 391
  MCH_PDU *mch_pduP;
  MCH_PDU  mch_pdu;
392
  //  uint8_t sync_area=255;
393
#endif
394

395
  int subframe = proc->subframe_tx;
396

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

468
void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
469

470 471
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int **txdataF = eNB->common_vars.txdataF[0];
472
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
473 474
  int subframe = proc->subframe_tx;
  int frame = proc->frame_tx;
475

476
  // generate Cell-Specific Reference Signals for both slots
477
  if (eNB->abstraction_flag==0) {
478 479 480 481 482 483 484 485 486 487 488 489 490 491
    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);
  }    
492

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

587
    /// generate PBCH
588
    if (eNB->abstraction_flag==0) {
589
      generate_pbch(&eNB->pbch,
590 591 592 593
                    txdataF,
                    AMP,
                    fp,
                    pbch_pdu,
594
                    frame&3);
595 596 597 598
    }
#ifdef PHY_ABSTRACTION
    else {
      generate_pbch_emul(eNB,pbch_pdu);
599
    }
600
#endif
601

602 603 604
  }
  else if ((subframe == 1) &&
	   (fp->frame_type == TDD)&&
605
	   (eNB->abstraction_flag==0)) {
606 607 608 609 610
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
611
  }
612 613 614 615
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
	   (fp->frame_type == FDD) &&
616
	   (eNB->abstraction_flag==0)) {
617 618 619 620 621 622 623 624 625 626
    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);
627

628
  }
629

630 631 632
  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
	   (fp->frame_type == TDD) &&
633
	   (eNB->abstraction_flag==0)) {
634 635 636 637 638
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
Raymond Knopp's avatar
 
Raymond Knopp committed
639
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
640

641 642 643
  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
	   (fp->frame_type == TDD) &&
644
	   (eNB->abstraction_flag==0)) {
645 646 647 648 649 650
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
651

652
}
Raymond Knopp's avatar
 
Raymond Knopp committed
653

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

656
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
657 658
  int frame = proc->frame_tx;
  int subframe = proc->subframe_tx;
659 660 661 662 663 664 665 666 667

  // 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,
668
				       &eNB->dlsch_SI,
669 670 671 672 673
				       fp,
				       eNB->pdsch_config_dedicated,
				       SI_RNTI,
				       0,
				       P_RNTI,
674
				       eNB->UE_stats[0].DL_pmi_single);
675 676
    
    
677
    eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE;
678
    
679
    LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
680
	  eNB->dlsch_SI->nCCE[subframe]);
681 682 683 684
    
#if defined(SMBV) 
    
    // configure SI DCI
685 686
    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);
687 688 689 690 691 692 693 694 695 696 697 698 699 700
      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,
701
				       &eNB->dlsch_ra,
702 703 704 705 706
				       fp,
				       eNB->pdsch_config_dedicated,
				       SI_RNTI,
				       dci_alloc->rnti,
				       P_RNTI,
707
				       eNB->UE_stats[0].DL_pmi_single);
708 709
    
    
710
    eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE;
711
    
712
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
713
	  eNB->dlsch_ra->nCCE[subframe]);
714 715 716
#if defined(SMBV) 
    
    // configure RA DCI
717 718
    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);
719
      smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", dci_alloc, i);
Raymond Knopp's avatar
 
Raymond Knopp committed
720
    }
721 722 723 724 725 726 727 728 729 730
    
#endif
    
  }
  
  else if ((dci_alloc->format != format0)&&
	   (dci_alloc->format != format3)&&
	   (dci_alloc->format != format3A)&&
	   (dci_alloc->format != format4)){ // this is a normal DLSCH allocation
    
Raymond Knopp's avatar
 
Raymond Knopp committed
731

732 733 734 735
    
    if (UE_id>=0) {
#if defined(SMBV) 
      // Configure this user
736 737
      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,
738 739
              dci_alloc->rnti,eNB->transmission_mode[(uint8_t)UE_id]);
	smbv_configure_user(smbv_fname,UE_id+1,eNB->transmission_mode[(uint8_t)UE_id],dci_alloc->rnti);
Raymond Knopp's avatar
 
Raymond Knopp committed
740
      }
741 742
      
#endif
743

744 745 746 747 748 749
      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,
750
					 eNB->dlsch[(uint8_t)UE_id],
751 752 753 754 755
					 fp,
					 eNB->pdsch_config_dedicated,
					 SI_RNTI,
					 0,
					 P_RNTI,
756
					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single);
757
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
758
	    eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
759 760
      
      
Cedric Roux's avatar
Cedric Roux committed
761 762 763
      T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
        T_INT(dci_alloc->rnti), T_INT(dci_alloc->format),
        T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid));
764

765
      eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
766
      
767
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"/%u\n",eNB->Mod_id,frame,subframe,
768
	    dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]);
769 770 771 772
      
#if defined(SMBV) 
      
      // configure UE-spec DCI
773 774
      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);
775
	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
776
      }
777
      
778
#endif
779 780 781
      
      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,
782
	    frame, subframe,UE_id,
783 784
	    dci_alloc->format,
	    1<<dci_alloc->L);
Raymond Knopp's avatar
 
Raymond Knopp committed
785
    } else {
786
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n",
787
	    eNB->Mod_id,frame,dci_alloc->rnti);
788
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
789
  }
790 791
  
}
792

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

795
  int harq_pid;
796
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
797
  int frame = proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
798
  int subframe = proc->subframe_tx;
799

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

859
}
860

861
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) {
862

863 864
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
865 866 867
  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;
868
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
869 870 871 872
  uint8_t *DLSCH_pdu=NULL;
  uint8_t DLSCH_pdu_tmp[768*8];
  uint8_t DLSCH_pdu_rar[256];
  int i;
873

874 875 876
  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,
877
	frame, subframe, input_buffer_length,
878 879 880 881 882
	get_G(fp,
	      dlsch_harq->nb_rb,
	      dlsch_harq->rb_alloc,
	      get_Qm(dlsch_harq->mcs),
	      dlsch_harq->Nl,
883
	      num_pdcch_symbols,frame,subframe),
884 885 886 887 888
	dlsch_harq->nb_rb,
	dlsch_harq->mcs,
	pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	dlsch_harq->rvidx,
	dlsch_harq->round);
889

890
#if defined(MESSAGE_CHART_GENERATOR_PHY)
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
  MSC_LOG_TX_MESSAGE(
		     MSC_PHY_ENB,MSC_PHY_UE,
		     NULL,0,
		     "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
		     frame, subframe,
		     input_buffer_length,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
			   get_Qm(dlsch_harq->mcs),
			   dlsch_harq->Nl,
			   num_pdcch_symbols,frame,subframe),
		     dlsch_harq->nb_rb,
		     dlsch_harq->mcs,
		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
		     dlsch_harq->rvidx,
		     dlsch_harq->round);
#endif

  if (ue_stats) ue_stats->dlsch_sliding_cnt++;

  if (dlsch_harq->round == 0) {

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

917 918 919 920 921 922 923
    if (eNB->mac_enabled==1) {
      if (ra_flag == 0) {
	DLSCH_pdu = mac_xface->get_dlsch_sdu(eNB->Mod_id,
					     eNB->CC_id,
					     frame,
					     dlsch->rnti,
					     0);
Raymond Knopp's avatar
 
Raymond Knopp committed
924
      }
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
      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;
940
	    
941 942 943 944 945 946 947 948 949 950
	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;
951
	      
952 953 954 955 956
	  generate_eNB_ulsch_params_from_rar(DLSCH_pdu,
					     frame,
					     (subframe),
					     eNB->ulsch[(uint32_t)UE_id],
					     fp);
957
	      
958
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 1;
959
	      
960 961 962 963 964 965 966 967 968 969 970
	  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
971

972 973 974 975 976 977 978 979 980
          /* 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;

981 982 983
          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
984 985 986
          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));
987
	}
988 989 990 991 992
	if (ue_stats) ue_stats->total_TBS_MAC += dlsch_harq->TBS;
      }
    }
    else {
      DLSCH_pdu = DLSCH_pdu_tmp;
993
	  
994 995 996
      for (i=0; i<input_buffer_length; i++)
	DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
    }
997 998
	
#if defined(SMBV) 
999

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

1006
#endif
1007 1008 1009



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

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

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

1019

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

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

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

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

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


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


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

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

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

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

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

1120
#endif
1121

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

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

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

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

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


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

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

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

1176
#if defined(SMBV) 
1177

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

1184
#endif
1185

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

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

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

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

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

1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
  /* 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;
      }
    }
  }

1257

1258
  num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
Raymond Knopp's avatar
Raymond Knopp committed
1259
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
1260 1261
        DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);

1262
#if defined(SMBV) 
Raymond Knopp's avatar
 
Raymond Knopp committed
1263
  // Sets up PDCCH and DCI table
1264 1265
  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);
1266
    dump_dci(fp,&DCI_pdu->dci_alloc[0]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1267 1268
    smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
  }
1269 1270
#endif

1271 1272
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);

1273
  // loop over all DCIs for this subframe to generate DLSCH allocations
1274 1275 1276 1277 1278
  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);
1279
    dci_alloc = &DCI_pdu->dci_alloc[i];
1280

1281 1282 1283 1284
    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);
1285 1286
      else
	UE_id = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1287
    }
1288 1289
    else UE_id=0;
    
1290
    generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
1291

Raymond Knopp's avatar
 
Raymond Knopp committed
1292
  }
1293

1294 1295
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

Raymond Knopp's avatar
 
Raymond Knopp committed
1296
  // Apply physicalConfigDedicated if needed
1297 1298 1299 1300
  // 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
1301
  for (i=0; i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) {
Cedric Roux's avatar
Cedric Roux committed
1302
    dci_alloc = &DCI_pdu->dci_alloc[i];
1303

1304 1305 1306
    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);
1307 1308
      else
	UE_id = i;
1309
      
1310
      if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
1311
	LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
1312
	mac_xface->macphy_exit("FATAL\n"); 
1313
      }
1314
      generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1315
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1316
  }
1317

1318 1319


Lionel Gauthier's avatar
Lionel Gauthier committed
1320 1321


Raymond Knopp's avatar
 
Raymond Knopp committed
1322 1323
  // 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
1324

1325 1326

  } else { // for emulation!!
1327 1328
    eNB->num_ue_spec_dci[(subframe)&1]=0;
    eNB->num_common_dci[(subframe)&1]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1329
  }
1330

1331
  if (eNB->abstraction_flag == 0) {
1332

1333
    if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) {
1334
      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,
1335
            DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
1336 1337
    }

1338 1339 1340 1341 1342 1343

    num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_ue_spec_dci,
                                         DCI_pdu->Num_common_dci,
                                         DCI_pdu->dci_alloc,
                                         0,
                                         AMP,
1344
                                         fp,
1345
                                         eNB->common_vars.txdataF[0],
1346
                                         subframe);
Raymond Knopp's avatar
Raymond Knopp committed
1347

Raymond Knopp's avatar
 
Raymond Knopp committed
1348
  }
1349

1350
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
Raymond Knopp's avatar
 
Raymond Knopp committed
1351
  else {
1352
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
1353
    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
1354
  }
1355

1356 1357
#endif

1358
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
1359

Raymond Knopp's avatar
 
Raymond Knopp committed
1360
  // Check for SI activity
1361

1362
  if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
1363

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

1366
#if defined(SMBV) 
1367

Raymond Knopp's avatar
 
Raymond Knopp committed
1368
    // Configures the data source of allocation (allocation is configured by DCI)
1369 1370
    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
1371 1372
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
    }
1373

1374
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1375
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1376

Raymond Knopp's avatar
 
Raymond Knopp committed
1377
  // Check for RA activity
1378
  if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
1379

1380
#if defined(SMBV) 
1381

1382
    // Configures the data source of allocation (allocation is configured by DCI)
1383 1384
    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);
1385 1386 1387
      smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length);
    }
    
1388
#endif
1389 1390
    
    
1391
    LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA),Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n",
1392
	  eNB->Mod_id,
1393
	  frame, subframe,
1394 1395
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
	  eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
1396
    
1397
    pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols);
1398 1399
    
    
1400
    eNB->dlsch_ra->active = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1401
  }
1402
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1403
  // Now scan UE specific DLSCH
1404
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
1405 1406 1407 1408
    {
      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)) {
1409

1410
	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);
1411 1412


Raymond Knopp's avatar
 
Raymond Knopp committed
1413
      }
1414

1415 1416 1417
      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)) {
1418

1419 1420
	// 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
1421
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1422
    }
1423

1424 1425


Raymond Knopp's avatar
 
Raymond Knopp committed
1426
  // if we have PHICH to generate
1427

1428
  if (is_phich_subframe(fp,subframe))
1429 1430 1431 1432
    {
      generate_phich_top(eNB,
			 proc,
			 AMP,
1433
			 0);
1434
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1435

1436 1437


1438
#ifdef EMOS
1439
  phy_procedures_emos_eNB_TX(subframe, eNB);
Raymond Knopp's avatar
 
Raymond Knopp committed
1440
#endif
1441

1442
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
1443
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
1444
  
1445 1446
}

1447
void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid)
1448
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1449
  // this prepares the demodulation of the first PUSCH of a new user, containing Msg3
1450 1451
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1452

Raymond Knopp's avatar
 
Raymond Knopp committed
1453
  LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
1454
        eNB->Mod_id,
1455
        frame,subframe,
1456 1457 1458 1459
        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;
1460

1461 1462 1463
  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))   {
1464

1465
    //    harq_pid = 0;
1466

1467 1468 1469
    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
1470
    LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
1471
          eNB->Mod_id,
1472
          frame,subframe,UE_id);
1473 1474 1475 1476 1477 1478 1479 1480 1481
  }
}


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

1482
void process_HARQ_feedback(uint8_t UE_id,
1483
                           PHY_VARS_eNB *eNB,
1484
			   eNB_rxtx_proc_t *proc,
1485 1486 1487 1488 1489
                           uint8_t pusch_flag,
                           uint8_t *pucch_payload,
                           uint8_t pucch_sel,
                           uint8_t SR_payload)
{
1490

1491
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1492
  uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe;
1493 1494
  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];
1495
  LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
1496
  uint8_t subframe_m4,M,m;
1497 1498
  int mp;
  int all_ACKed=1,nb_alloc=0,nb_ACK=0;
1499 1500
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1501
  int harq_pid = subframe2harq_pid( fp,frame,subframe);
1502 1503


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

1507 1508
    dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
    M=1;
1509

1510
    if (pusch_flag == 1) {
1511
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1512
      if (dlsch->subframe_tx[subframe_m4]==1)
1513 1514
	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);
1515 1516
    }
    else {
1517
      dlsch_ACK[0] = pucch_payload[0];
1518
      LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",eNB->Mod_id,
1519
	    frame,dlsch_ACK[0],subframe_m4);
kaltenbe's avatar
kaltenbe committed
1520
      /*
1521
	if (dlsch_ACK[0]==0)
1522
	AssertFatal(0,"Exiting on NAK on PUCCH\n");
kaltenbe's avatar
kaltenbe committed
1523
      */
1524
    }
1525

Lionel Gauthier's avatar
Lionel Gauthier committed
1526 1527 1528

#if defined(MESSAGE_CHART_GENERATOR_PHY)
    MSC_LOG_RX_MESSAGE(
1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
		       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
1539
#endif
1540 1541
  } else { // TDD Handle M=1,2 cases only

1542
    M=ul_ACK_subframe2_M(fp,
1543 1544
                         subframe);

1545 1546 1547 1548 1549 1550 1551 1552
    // 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

1553
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1554
      dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling)
1555
	?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];
1556
    }
1557

1558
    else {  // PUCCH ACK/NAK
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593
      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;
        }
1594
      }
1595
    }
1596 1597 1598 1599
  }

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

    for (m=0; m<M; m++) {
1603
      dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1604 1605
						 subframe,
						 m);
1606 1607 1608

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

1611 1612
    if (nb_alloc == nb_ACK)
      all_ACKed = 1;
1613
    else
1614
      all_ACKed = 0;
1615 1616 1617
  }


1618
  for (m=0,mp=-1; m<M; m++) {
1619

1620
    dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1621 1622
					       subframe,
					       m);
1623

1624 1625
    if (dlsch->subframe_tx[dl_subframe]==1) {
      if (pusch_flag == 1)
1626
        mp++;
1627
      else
1628
        mp = m;
1629

1630
      dl_harq_pid[m]     = dlsch->harq_ids[dl_subframe];
1631

1632
      if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
1633 1634 1635 1636
        if ((SR_payload == 1)&&(all_ACKed == 1))
          dlsch_ACK[m] = 1;
        else
          dlsch_ACK[m] = 0;
1637
      }
1638

1639
      if (dl_harq_pid[m]<dlsch->Mdlharq) {
1640 1641
        dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
1642
        LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id,
1643 1644 1645 1646 1647 1648 1649 1650 1651
              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");

1652
#endif
1653 1654 1655 1656 1657 1658 1659 1660

        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
1661
            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,
1662
                  dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
1663
#endif
1664

1665
            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),
1666
              T_INT(dl_harq_pid[m]));
1667

1668 1669 1670 1671 1672 1673 1674 1675 1676
            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++;

1677

1678
            if (dlsch_harq_proc->round == dlsch->Mlimit) {
1679 1680
              // This was the last round for DLSCH so reset round and increment l2_error counter
#ifdef DEBUG_PHY_PROC
1681
              LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",eNB->Mod_id,
1682
                    dlsch->rnti,dl_harq_pid[m]);
1683
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1684
#if defined(MESSAGE_CHART_GENERATOR_PHY)
1685
              MSC_LOG_EVENT(MSC_PHY_ENB, "0 HARQ DLSCH Failed RNTI %"PRIx16" round %u",
1686 1687
                            dlsch->rnti,
                            dlsch_harq_proc->round);
Lionel Gauthier's avatar
Lionel Gauthier committed
1688
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1689

1690 1691 1692 1693 1694 1695 1696
              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
1697
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
1698
                  dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
1699
#endif
1700

1701
            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),
1702
              T_INT(dl_harq_pid[m]));
1703

1704 1705 1706 1707 1708 1709 1710 1711
            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 +
1712
	      eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1713 1714
            /*
              ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
1715
              eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729
            */
          }

          // 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);
1730
#endif
1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752

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


        }
1753
      }
1754
    }
1755 1756 1757
  }
}

1758
void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
1759
		      eNB_rxtx_proc_t *proc,
1760 1761 1762 1763 1764 1765
                      uint8_t UE_id,
                      int16_t *n1_pucch0,
                      int16_t *n1_pucch1,
                      int16_t *n1_pucch2,
                      int16_t *n1_pucch3)
{
1766

1767
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
1768
  uint8_t nCCE0,nCCE1;
1769
  int sf;
1770 1771
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1772 1773

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

1776 1777
    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];
1778
      *n1_pucch1 = -1;
1779
    } else {
1780 1781 1782
      *n1_pucch0 = -1;
      *n1_pucch1 = -1;
    }
1783
  } else {
1784

1785 1786 1787
    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
1788
        /*  if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
1789 1790 1791 1792 1793
	    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;*/
1794

1795 1796
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1797 1798 1799 1800 1801 1802 1803
          *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

1804 1805
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1806 1807 1808 1809 1810 1811 1812 1813 1814
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;

        *n1_pucch1 = -1;

      } else if (subframe == 7) { // ACK subframes 0 and 1
        //harq_ack[0].nCCE;
        //harq_ack[1].nCCE;
1815 1816
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1817 1818 1819 1820 1821 1822 1823
          *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;
1824 1825
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4];
1826 1827 1828 1829 1830 1831 1832
          *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",
1833
              eNB->Mod_id,
1834 1835 1836
              frame,
              subframe,frame_parms->tdd_config);
        return;
1837
      }
1838

1839
      break;
1840

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

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

1858 1859
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[8];
1860 1861 1862 1863 1864
          *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;

1865 1866
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7];
1867 1868 1869 1870 1871
          *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
1872 1873
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1874 1875 1876 1877
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1878 1879
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1880 1881 1882 1883 1884
          *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",
1885
              eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
1886
        return;
1887
      }
1888

1889
      break;
1890 1891
    }  // switch tdd_config

1892 1893 1894
    // Don't handle the case M>2
    *n1_pucch2 = -1;
    *n1_pucch3 = -1;
1895 1896 1897
  }
}

1898
void prach_procedures(PHY_VARS_eNB *eNB) {
1899

1900
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1901 1902 1903 1904
  uint16_t preamble_energy_list[64],preamble_delay_list[64];
  uint16_t preamble_max,preamble_energy_max;
  uint16_t i;
  int8_t UE_id;
1905 1906
  int subframe = eNB->proc.subframe_prach;
  int frame = eNB->proc.frame_prach;
1907
  uint8_t CC_id = eNB->CC_id;
1908

1909
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
1910 1911
  memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
  memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
1912

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

1917

1918
    rx_prach(eNB,
1919 1920 1921 1922 1923 1924 1925
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
  } else {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {

1926
      LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
1927
            UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
1928
            PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
1929
            fp->prach_config_common.rootSequenceIndex,
1930 1931
            PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex);

Raymond Knopp's avatar
 
Raymond Knopp committed
1932
      if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) &&
1933
          (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex ==
1934
           fp->prach_config_common.rootSequenceIndex) ) {
1935 1936 1937
        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;

1938
      }
1939
    }
1940
  }
1941

1942 1943 1944
  preamble_energy_max = preamble_energy_list[0];
  preamble_max = 0;

1945
  for (i=1; i<64; i++) {
1946 1947 1948 1949
    if (preamble_energy_max < preamble_energy_list[i]) {
      preamble_energy_max = preamble_energy_list[i];
      preamble_max = i;
    }
1950 1951 1952
  }

#ifdef DEBUG_PHY_PROC
1953
  LOG_D(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
1954 1955 1956
        preamble_max,
        preamble_energy_list[preamble_max],
        preamble_delay_list[preamble_max]);
1957 1958
#endif

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

1961
    UE_id = find_next_ue_index(eNB);
1962
 
1963
    if (UE_id>=0) {
1964
      eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
1965

1966
      eNB->UE_stats[(uint32_t)UE_id].sector = 0;
1967
      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",
1968 1969
            eNB->Mod_id,
            eNB->CC_id,
1970 1971
            frame,
            subframe,
1972
	    UE_id,
1973 1974 1975 1976
            preamble_max,
            preamble_energy_max/10,
            preamble_energy_max%10,
            preamble_delay_list[preamble_max]);
1977

Cedric Roux's avatar
Cedric Roux committed
1978 1979 1980
      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]));

1981
      if (eNB->mac_enabled==1) {
1982 1983
        uint8_t update_TA=4;

1984
        switch (fp->N_RB_DL) {
1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001
        case 6:
          update_TA = 16;
          break;

        case 25:
          update_TA = 4;
          break;

        case 50:
          update_TA = 2;
          break;

        case 100:
          update_TA = 1;
          break;
        }

2002 2003 2004 2005 2006 2007
	mac_xface->initiate_ra_proc(eNB->Mod_id,
				    eNB->CC_id,
				    frame,
				    preamble_max,
				    preamble_delay_list[preamble_max]*update_TA,
				    0,subframe,0);
2008 2009
      }      

2010
    } else {
2011
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many");
2012
      LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
2013
            eNB->Mod_id,frame, subframe);
2014
    }
2015
  }
2016
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
2017 2018
}

Cedric Roux's avatar
Cedric Roux committed
2019 2020
void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid)
{
2021
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2022
  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
2023
  int16_t n1_pucch0 = -1, n1_pucch1 = -1, n1_pucch2 = -1, n1_pucch3 = -1;
2024 2025
  uint8_t do_SR = 0;
  uint8_t pucch_sel = 0;
2026
  int32_t metric0=0,metric1=0,metric0_SR=0;
2027 2028
  ANFBmode_t bundling_flag;
  PUCCH_FMT_t format;
2029 2030
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2031

2032 2033
  if ((eNB->dlsch[UE_id][0]) &&
      (eNB->dlsch[UE_id][0]->rnti>0) &&
Cedric Roux's avatar
Cedric Roux committed
2034
      (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) {
2035

2036
    // check SR availability
2037 2038
    do_SR = is_SR_subframe(eNB,proc,UE_id);
    //      do_SR = 0;
Cedric Roux's avatar
Cedric Roux committed
2039

2040 2041
    // Now ACK/NAK
    // First check subframe_tx flag for earlier subframes
2042

2043
    get_n1_pucch_eNB(eNB,
Cedric Roux's avatar
Cedric Roux committed
2044 2045 2046 2047 2048 2049 2050
                     proc,
                     UE_id,
                     &n1_pucch0,
                     &n1_pucch1,
                     &n1_pucch2,
                     &n1_pucch3);

2051
    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
2052 2053 2054 2055
          eNB->Mod_id,eNB->dlsch[UE_id][0]->rnti,
          frame,subframe,
          n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,do_SR);

2056 2057 2058
    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
2059

2060 2061 2062
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
Cedric Roux's avatar
Cedric Roux committed
2063 2064
        eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
        break;
2065
      case 15:
Cedric Roux's avatar
Cedric Roux committed
2066 2067
        eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
        break;
2068
      case 25:
Cedric Roux's avatar
Cedric Roux committed
2069 2070
        eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
        break;
2071
      case 50:
Cedric Roux's avatar
Cedric Roux committed
2072 2073 2074
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
        break;
2075
      case 75:
Cedric Roux's avatar
Cedric Roux committed
2076 2077 2078
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
        break;
2079
      case 100:
Cedric Roux's avatar
Cedric Roux committed
2080 2081 2082
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
        break;
2083
      default:
Cedric Roux's avatar
Cedric Roux committed
2084 2085
        LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
        break;
2086
      }
Cedric Roux's avatar
Cedric Roux committed
2087

2088
      if (do_SR == 1) {
Cedric Roux's avatar
Cedric Roux committed
2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110
        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);
        }
2111
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2112 2113 2114 2115 2116 2117 2118 2119 2120 2121
        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);
        }
2122
#endif
2123
      }// do_SR==1
Cedric Roux's avatar
Cedric Roux committed
2124

2125
      if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR
Cedric Roux's avatar
Cedric Roux committed
2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143
      } 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);
        }
2144
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2145 2146 2147 2148 2149 2150 2151 2152
        else {
          metric0 = rx_pucch_emul(eNB,
                                  proc,
                                  UE_id,
                                  pucch_format1a,
                                  0,
                                  pucch_payload0);
        }
2153
#endif
Cedric Roux's avatar
Cedric Roux committed
2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185

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

2186
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2187 2188 2189 2190 2191
        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);
2192
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
2193

Cedric Roux's avatar
Cedric Roux committed
2194 2195 2196 2197 2198 2199 2200
        process_HARQ_feedback(UE_id,eNB,proc,
                            0,// pusch_flag
                            pucch_payload0,
                            2,
                            SR_payload);
      } // FDD
      else {  //TDD
2201

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

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

Cedric Roux's avatar
Cedric Roux committed
2206 2207 2208 2209 2210 2211 2212
        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;
        }
2213

Cedric Roux's avatar
Cedric Roux committed
2214 2215
        // if SR was detected, use the n1_pucch from SR
        if (SR_payload==1) {
2216
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2217 2218 2219 2220
          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);
2221
#endif
2222

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

Cedric Roux's avatar
Cedric Roux committed
2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291
          // 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 {
2292
#ifdef PHY_ABSTRACTION
Cedric Roux's avatar
Cedric Roux committed
2293 2294 2295 2296 2297 2298
              metric1 = rx_pucch_emul(eNB,
                                      proc,
                                      UE_id,
                                      format,
                                      1,
                                      pucch_payload1);
2299
#endif
Cedric Roux's avatar
Cedric Roux committed
2300 2301 2302
            }
          }
        }
2303

Cedric Roux's avatar
Cedric Roux committed
2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319
        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
        }
2320

2321
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
2322 2323 2324 2325
        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]);
2326
#endif
Cedric Roux's avatar
Cedric Roux committed
2327 2328 2329 2330 2331 2332
        process_HARQ_feedback(UE_id,eNB,proc,
                              0,// pusch_flag
                              pucch_payload,
                              pucch_sel,
                              SR_payload);
      } // TDD
2333
    }
Cedric Roux's avatar
Cedric Roux committed
2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356

    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);
      }
    }
  }
2357
}
2358

2359

2360
void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
2361

2362 2363
  uint8_t access_mode;
  int num_active_cba_groups;
2364 2365
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2366 2367
  uint16_t rnti=0;
  int ret=0;
2368
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2369

2370 2371
  if (eNB->ulsch[UE_id]==NULL) return;

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

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

2519
}
2520

2521 2522 2523 2524
typedef struct {
  PHY_VARS_eNB *eNB;
  int slot;
} fep_task;
2525

2526
void fep0(PHY_VARS_eNB *eNB,int slot) {
2527

2528 2529 2530
  eNB_proc_t *proc       = &eNB->proc;
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  int l;
2531

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

2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544
  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
		);
  }
}
2545

2546

Raymond Knopp's avatar
Raymond Knopp committed
2547

2548 2549 2550 2551 2552 2553 2554
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
2555

2556 2557 2558
    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
2559 2560 2561 2562

    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" );
2563
      return NULL;
Raymond Knopp's avatar
Raymond Knopp committed
2564
    }
2565
  }
Raymond Knopp's avatar
Raymond Knopp committed
2566 2567 2568 2569 2570 2571



  return(NULL);
}

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

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

2576 2577 2578 2579 2580 2581
  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
2582 2583


2584 2585
}

2586 2587 2588
extern void *td_thread(void*);

void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
2589 2590 2591

  eNB_proc_t *proc = &eNB->proc;

2592 2593
  proc->tdp.eNB = eNB;
  proc->instance_cnt_td         = -1;
2594
    
2595 2596
  pthread_mutex_init( &proc->mutex_td, NULL);
  pthread_cond_init( &proc->cond_td, NULL);
2597

2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615
  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);
2616 2617 2618

}

Raymond Knopp's avatar
Raymond Knopp committed
2619

2620 2621 2622
void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) {

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

2624
  struct timespec wait;
2625

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

2647

2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658
  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
2659
  wait_on_busy_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread");  
2660

2661
  stop_meas(&eNB->ofdm_demod_stats);
2662 2663
}

Raymond Knopp's avatar
Raymond Knopp committed
2664 2665


Raymond Knopp's avatar
Raymond Knopp committed
2666
void eNB_fep_full(PHY_VARS_eNB *eNB) {
2667

Raymond Knopp's avatar
Raymond Knopp committed
2668
  eNB_proc_t *proc = &eNB->proc;
2669
  int l;
2670
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2671

2672
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
2673
  start_meas(&eNB->ofdm_demod_stats);
2674 2675 2676 2677 2678 2679 2680
  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
2681
		0,
2682 2683 2684 2685 2686 2687 2688 2689 2690 2691
		0
		);
    slot_fep_ul(fp,
		&eNB->common_vars,
		l,
		1+(proc->subframe_rx<<1),
		0,
		0
		);
  }
2692
  stop_meas(&eNB->ofdm_demod_stats);
2693 2694 2695 2696 2697 2698
  
  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
2699
  }    
2700 2701
}

Raymond Knopp's avatar
Raymond Knopp committed
2702
void eNB_fep_rru_if5(PHY_VARS_eNB *eNB) {
2703

Raymond Knopp's avatar
Raymond Knopp committed
2704
  eNB_proc_t *proc=&eNB->proc;
2705 2706 2707 2708 2709 2710 2711 2712 2713
  uint8_t seqno=0;

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

}

Raymond Knopp's avatar
Raymond Knopp committed
2714
void do_prach(PHY_VARS_eNB *eNB) {
2715

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

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

2754
}
2755

2756 2757 2758
void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){


Raymond Knopp's avatar
Raymond Knopp committed
2759 2760 2761 2762
  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;
2763
  int offset             = (eNB->single_thread_flag==1) ? 0 : (subframe&1);
Sandeep Kumar's avatar
Sandeep Kumar committed
2764

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

Raymond Knopp's avatar
Raymond Knopp committed
2767 2768 2769
  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 );
2770
  
2771
  start_meas(&eNB->phy_proc_rx);
2772
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe);
2773

Raymond Knopp's avatar
Raymond Knopp committed
2774

Raymond Knopp's avatar
Raymond Knopp committed
2775
  if (eNB->fep) eNB->fep(eNB);
2776

Raymond Knopp's avatar
Raymond Knopp committed
2777
  if (eNB->do_prach) eNB->do_prach(eNB);
2778

Raymond Knopp's avatar
Raymond Knopp committed
2779
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 0 );
2780 2781
}

2782

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

2795
  const int subframe = proc->subframe_rx;
Raymond Knopp's avatar
Raymond Knopp committed
2796 2797
  const int frame    = proc->frame_rx;
  int offset         = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1;
2798

2799

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

Raymond Knopp's avatar
Raymond Knopp committed
2802
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
2803

2804
#ifdef DEBUG_PHY_PROC
2805
  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
2806
#endif
2807

2808
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
2809

2810
  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
2811
    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
2812
             eNB->frame_parms.samples_per_tti * 4));
2813

2814 2815 2816 2817
  eNB->rb_mask_ul[0]=0;
  eNB->rb_mask_ul[1]=0;
  eNB->rb_mask_ul[2]=0;
  eNB->rb_mask_ul[3]=0;
2818 2819 2820



2821
  // Check for active processes in current subframe
2822
  harq_pid = subframe2harq_pid(fp,
2823
                               frame,subframe);
2824

2825 2826
  // reset the cba flag used for collision detection
  for (i=0; i < NUM_MAX_CBA_GROUP; i++) {
2827
    eNB->cba_last_reception[i]=0;
2828
  }
2829

2830
  // Do PUCCH processing first
2831

2832
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2833
    pucch_procedures(eNB,proc,i,harq_pid);
2834
  }
2835

2836
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2837

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

2845

2846 2847 2848
    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;
2849

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

2863

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

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

2881

2882
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
2883

2884
      eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
2885
				    nPRS)%12;
2886

2887
      if (fp->frame_type == FDD ) {
2888
        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
2889

2890 2891
        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
2892
        } else {
2893
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
2894
        }
2895
      }
2896

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

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

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

2933
#endif
2934
      stop_meas(&eNB->ulsch_demodulation_stats);
2935

2936

2937
      start_meas(&eNB->ulsch_decoding_stats);
2938

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

2947 2948
#ifdef PHY_ABSTRACTION
      else {
2949 2950
        ret = ulsch_decoding_emul(eNB,
				  proc,
2951 2952 2953
                                  i,
                                  &rnti);
      }
2954

2955
#endif
2956
      stop_meas(&eNB->ulsch_decoding_stats);
2957

2958
      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",
2959
            eNB->Mod_id,harq_pid,
2960
            frame,subframe,
2961 2962 2963 2964 2965 2966 2967 2968 2969
            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],
2970
            ret);
2971

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

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

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

2995
      }
2996

2997
      if (eNB->ulsch[i]->Msg3_flag == 1)
2998
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
2999

3000
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
3001
        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),
3002
          T_INT(harq_pid));
3003

3004 3005 3006 3007
        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++;
3008

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

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

	  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",
3020
		eNB->Mod_id,harq_pid,
3021
		frame,subframe,
3022 3023 3024 3025 3026 3027 3028 3029 3030
		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],
3031 3032
		ret);

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

3046 3047
            eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
            //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0;
3048 3049

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

3053
            get_Msg3_alloc_ret(fp,
3054
                               subframe,
3055
                               frame,
3056 3057
                               &eNB->ulsch[i]->Msg3_frame,
                               &eNB->ulsch[i]->Msg3_subframe);
Cedric Roux's avatar
Cedric Roux committed
3058

3059 3060 3061
            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
3062 3063 3064
            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));
3065
          }
3066 3067
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
3068

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

#if defined(MESSAGE_CHART_GENERATOR_PHY)
          MSC_LOG_RX_DISCARDED_MESSAGE(
3080 3081 3082 3083 3084 3085 3086
				       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
				       );
3087
#endif
3088

3089
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) {
3090
            LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
3091
                  eNB->Mod_id,harq_pid,
3092
                  frame,subframe, i,
3093
                  eNB->ulsch[i]->Mlimit);
3094

3095 3096 3097 3098
            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++;
3099 3100

	    // indicate error to MAC
3101 3102 3103 3104 3105 3106 3107 3108 3109
	    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);
3110 3111 3112 3113
          }
        }
      }  // ulsch in error
      else {
3114 3115 3116



3117
        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),
3118 3119
          T_INT(harq_pid));

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

3163
        if (eNB->ulsch[i]->Msg3_flag == 1) {
3164
	  if (eNB->mac_enabled==1) {
3165

3166
	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
3167
		  eNB->Mod_id,
3168
		  frame,harq_pid,i);
3169 3170 3171 3172 3173 3174 3175 3176 3177
	    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);
3178 3179
	    
	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
3180 3181
	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	      eNB->UE_stats[i].mode = PRACH;
3182 3183
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
3184
					frame,
3185 3186 3187
					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;
3188 3189 3190
	    } // Msg3_flag == 0
	    
	  } // mac_enabled==1
3191

3192 3193
          eNB->UE_stats[i].mode = PUSCH;
          eNB->ulsch[i]->Msg3_flag = 0;
3194

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

3197
          for (k=0; k<8; k++) { //harq_processes
3198 3199 3200 3201
            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;
3202
            }
3203

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

3208 3209 3210 3211 3212
            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;
3213
            }
3214 3215
          }

3216 3217 3218
          eNB->UE_stats[i].dlsch_sliding_cnt=0;
          eNB->UE_stats[i].dlsch_NAK_round0=0;
          eNB->UE_stats[i].dlsch_mcs_offset=0;
3219 3220 3221
        } // Msg3_flag==1
	else {  // Msg3_flag == 0

3222
#ifdef DEBUG_PHY_PROC
3223 3224
#ifdef DEBUG_ULSCH
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
3225
                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
3226

3227 3228
          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]);
3229 3230 3231

          LOG_T(PHY,"\n");
#endif
3232
#endif
3233

3234
	  if (eNB->mac_enabled==1) {
3235

3236 3237
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
3238
			      frame,subframe,
3239 3240 3241
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
3242 3243
			      harq_pid,
			      NULL);
3244

3245
#ifdef LOCALIZATION
3246 3247
	    start_meas(&eNB->localization_stats);
	    aggregate_eNB_UE_localization_stats(eNB,
3248 3249 3250
						i,
						frame,
						subframe,
3251 3252
						get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
	    stop_meas(&eNB->localization_stats);
3253
#endif
3254 3255 3256
	    
	  } // mac_enabled==1
        } // Msg3_flag == 0
3257

3258
        // estimate timing advance for MAC
3259
        if (eNB->abstraction_flag == 0) {
3260
          sync_pos = lte_est_timing_advance_pusch(eNB,i);
3261
          eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
3262
        }
3263

3264 3265
#ifdef DEBUG_PHY_PROC
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
3266
              eNB->Mod_id,
3267 3268
              frame, subframe,
              i,
3269
              eNB->UE_stats[i].timing_advance_update);
3270
#endif
3271 3272


3273 3274 3275
      }  // ulsch not in error

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


3315
    // update ULSCH statistics for tracing
3316
    if ((frame % 100 == 0) && (subframe == 4)) {
3317
      for (harq_idx=0; harq_idx<8; harq_idx++) {
3318 3319 3320 3321 3322 3323 3324 3325
        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]);
3326
          } else {
3327
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
3328 3329
          }

3330 3331 3332 3333
          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];
3334
        }
3335 3336
      }
    }
3337

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3338
    if ((frame % 100 == 0) && (subframe==4)) {
3339
      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
3340
					eNB->UE_stats[i].total_TBS_last);
3341

3342
      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
3343
    }
3344

3345
    // CBA (non-LTE)
3346
    cba_procedures(eNB,proc,i,harq_pid);
3347 3348
  } // loop i=0 ... NUMBER_OF_UE_MAX-1

3349
  if (eNB->abstraction_flag == 0) {
3350
    lte_eNB_I0_measurements(eNB,
3351 3352
			    subframe,
			    0,
3353 3354
			    eNB->first_run_I0_measurements);
    eNB->first_run_I0_measurements = 0;
3355
  }
3356

3357
#ifdef PHY_ABSTRACTION
3358 3359 3360 3361
  else {
    lte_eNB_I0_measurements_emul(eNB,
				 0);
  }
3362

3363
#endif
3364 3365


3366
  //}
3367 3368

#ifdef EMOS
3369
  phy_procedures_emos_eNB_RX(subframe,eNB);
3370 3371
#endif

Raymond Knopp's avatar
Raymond Knopp committed
3372
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
3373

3374
  stop_meas(&eNB->phy_proc_rx);
3375

3376 3377 3378 3379
}

#undef DEBUG_PHY_PROC

3380 3381 3382 3383
#ifdef Rel10
int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type)
{

3384
  int do_proc=0;// do nothing
3385 3386

  switch(r_type) {
3387
  case no_relay:
3388
    do_proc= no_relay; // perform the normal eNB operation
3389
    break;
3390

3391
  case multicast_relay:
3392
    if (((next_slot >>1) < 6) || ((next_slot >>1) > 8))
3393
      do_proc = 0; // do nothing
3394 3395 3396
    else // SF#6, SF#7 and SF#8
      do_proc = multicast_relay; // do PHY procedures eNB TX

3397
    break;
3398

3399 3400
  default: // should'not be here
    LOG_W(PHY,"Not supported relay type %d, do nothing\n", r_type);
3401
    do_proc=0;
3402 3403
    break;
  }
3404

3405 3406
  return do_proc;
}
3407
#endif