phy_procedures_lte_eNb.c 110 KB
Newer Older
Raymond Knopp's avatar
Raymond Knopp committed
1

2
/*******************************************************************************
3
    OpenAirInterface
ghaddab's avatar
ghaddab committed
4
    Copyright(c) 1999 - 2014 Eurecom
5

ghaddab's avatar
ghaddab committed
6 7 8 9
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
10 11


ghaddab's avatar
ghaddab committed
12 13 14 15
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
16

ghaddab's avatar
ghaddab committed
17
    You should have received a copy of the GNU General Public License
18 19
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
ghaddab's avatar
ghaddab committed
20
   see <http://www.gnu.org/licenses/>.
21 22

  Contact Information
ghaddab's avatar
ghaddab committed
23 24
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
25
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
26

ghaddab's avatar
ghaddab committed
27
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
28

ghaddab's avatar
ghaddab committed
29
 *******************************************************************************/
30 31 32

/*! \file phy_procedures_lte_eNB.c
 * \brief Implementation of eNB procedures from 36.213 LTE specifications
33
 * \author R. Knopp, F. Kaltenberger, N. Nikaein
34 35 36
 * \date 2011
 * \version 0.1
 * \company Eurecom
37
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr
38 39 40 41 42 43 44 45 46 47 48 49 50
 * \note
 * \warning
 */

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

#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif

51
//#define DEBUG_PHY_PROC (Already defined in cmake)
52 53 54 55 56 57 58
//#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"

59
#include "assertions.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
60
#include "msc.h"
61

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

66 67 68 69 70 71
//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

72 73
void exit_fun(const char* s);

74 75
extern int exit_openair;

76
extern openair0_device openair0;
77

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

83
extern uint16_t hundred_times_log10_NPRB[100];
84

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

//DCI_ALLOC_t dci_alloc[8];

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

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

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

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

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

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

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

  return(0);
}
133

134 135 136 137 138 139
void put_harq_pid_in_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid)
{
  DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->tail_freelist] = harq_pid;
  DLSCH_ptr->tail_freelist = (DLSCH_ptr->tail_freelist + 1) % 10;
}

Cedric Roux's avatar
Cedric Roux committed
140
void remove_harq_pid_from_freelist(LTE_eNB_DLSCH_t *DLSCH_ptr, int harq_pid)
141 142 143 144 145
{
  if (DLSCH_ptr->head_freelist == DLSCH_ptr->tail_freelist) {
    LOG_E(PHY, "%s:%d: you cannot read this!\n", __FILE__, __LINE__);
    abort();
  }
Cedric Roux's avatar
Cedric Roux committed
146 147 148 149 150 151 152 153 154
  /* basic check, in case several threads deal with the free list at the same time
   * in normal situations it should not happen, that's also why we don't use any
   * locking mechanism to protect the free list
   * to be refined in case things don't work properly
   */
  if (harq_pid != DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist]) {
    LOG_E(PHY, "%s:%d: critical error, get in touch with the authors\n", __FILE__, __LINE__);
    abort();
  }
155 156 157
  DLSCH_ptr->head_freelist = (DLSCH_ptr->head_freelist + 1) % 10;
}

158
int32_t add_ue(int16_t rnti, PHY_VARS_eNB *eNB)
159
{
160
  uint8_t i;
161

Raymond Knopp's avatar
 
Raymond Knopp committed
162
#ifdef DEBUG_PHY_PROC
163
  LOG_I(PHY,"[eNB %d/%d] Adding UE with rnti %x\n",
164 165
        eNB->Mod_id,
        eNB->CC_id,
166
        (uint16_t)rnti);
Raymond Knopp's avatar
 
Raymond Knopp committed
167
#endif
168 169

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
170
    if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) {
171
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed add ue %"PRIx16" (ENOMEM)", rnti);
172 173
      LOG_E(PHY,"Can't add UE, not enough memory allocated\n");
      return(-1);
174
    } else {
175
      if (eNB->UE_stats[i].crnti==0) {
176
        MSC_LOG_EVENT(MSC_PHY_ENB, "0 Add ue %"PRIx16" ", rnti);
177
        LOG_D(PHY,"UE_id %d associated with rnti %x\n",i, (uint16_t)rnti);
178 179 180
        eNB->dlsch[i][0]->rnti = rnti;
        eNB->ulsch[i]->rnti = rnti;
        eNB->UE_stats[i].crnti = rnti;
181

182 183 184
	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));
185
	LOG_D(PHY,"Initializing Po_PUCCH: p0_NominalPUCCH %d, gain %d => %d\n",
186 187 188
	      eNB->frame_parms.ul_power_control_config_common.p0_NominalPUCCH,
	      eNB->rx_total_gain_dB,
	      eNB->UE_stats[i].Po_PUCCH);
189
  
190
        return(i);
191
      }
192
    }
193 194 195 196
  }
  return(-1);
}

197
int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) {
198
  uint8_t i;
199
  int j,CC_id;
200
  PHY_VARS_eNB *eNB;
201 202

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
203
    eNB = PHY_vars_eNB_g[Mod_idP][CC_id];
204
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
205
      if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) {
206 207 208 209
	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 {
210
	if (eNB->UE_stats[i].crnti==rntiP) {
211
	  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Removed ue %"PRIx16" ", rntiP);
212
#ifdef DEBUG_PHY_PROC
213
	  LOG_I(PHY,"eNB %d removing UE %d with rnti %x\n",eNB->Mod_id,i,rnti);
214
#endif
215
	  //LOG_D(PHY,("[PHY] UE_id %d\n",i);
216 217 218 219
	  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));
220 221 222
	  //  mac_exit_wrapper("Removing UE");
	  
	  /* clear the harq pid freelist */
223 224
	  eNB->dlsch[i][0]->head_freelist = 0;
	  eNB->dlsch[i][0]->tail_freelist = 0;
225
	  for (j = 0; j < 8; j++)
226
	    put_harq_pid_in_freelist(eNB->dlsch[i][0], j);
227 228 229
	  
	  return(i);
	}
230
      }
231
    }
232
  }
233
  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (not found)", rntiP);
234 235 236
  return(-1);
}

237
int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
238
{
239
  uint8_t i;
240

241
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
242 243 244 245
    if (eNB->UE_stats[i].crnti==0) {
      /*if ((eNB->dlsch[i]) &&
      (eNB->dlsch[i][0]) &&
      (eNB->dlsch[i][0]->rnti==0))*/
246 247 248
      LOG_D(PHY,"Next free UE id is %d\n",i);
      return(i);
    }
249
  }
250

251 252 253
  return(-1);
}

Lionel Gauthier's avatar
Lionel Gauthier committed
254
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)
255 256 257 258
{
  LTE_eNB_DLSCH_t *DLSCH_ptr;
  LTE_eNB_ULSCH_t *ULSCH_ptr;
  uint8_t ulsch_subframe,ulsch_frame;
259
  uint8_t i;
Raymond Knopp's avatar
 
Raymond Knopp committed
260
  int8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]);
261
  int sf1=(10*frame)+subframe,sf2,sfdiff,sfdiff_max=7;
262 263

  if (UE_id==-1) {
264
    LOG_D(PHY,"Cannot find UE with rnti %x (Mod_id %d, CC_id %d)\n",rnti, Mod_id, CC_id);
265 266
    *round=0;
    return(-1);
267 268 269
  }

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

272 273 274 275 276
    // set to no available process first
    *harq_pid = -1;

    for (i=0; i<DLSCH_ptr->Mdlharq; i++) {
      if (DLSCH_ptr->harq_processes[i]!=NULL) {
277
	if (DLSCH_ptr->harq_processes[i]->status == ACTIVE) {
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
	  sf2 = (DLSCH_ptr->harq_processes[i]->frame*10) + DLSCH_ptr->harq_processes[i]->subframe;
	  if (sf2<=sf1)
	    sfdiff = sf1-sf2;
	  else // this happens when wrapping around 1024 frame barrier
	    sfdiff = 10240 + sf1-sf2;
	  LOG_D(PHY,"process %d is active, round %d (waiting %d)\n",i,DLSCH_ptr->harq_processes[i]->round,sfdiff);

	  if (sfdiff>sfdiff_max) { // this is an active process that is waiting longer than the others (and longer than 7 ms)
	    sfdiff_max = sfdiff; 
	    *harq_pid = i;
	    *round = DLSCH_ptr->harq_processes[i]->round;
	  }
	}
      } else { // a process is not defined
	LOG_E(PHY,"[eNB %d] DLSCH process %d for rnti %x (UE_id %d) not allocated\n",Mod_id,i,rnti,UE_id);
	return(-1);
294
      }
295
    }
296 297 298 299 300 301 302 303

    /* if no active harq pid, get the oldest in the freelist, if any */
    if (*harq_pid == 255 && DLSCH_ptr->head_freelist != DLSCH_ptr->tail_freelist) {
      *harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
      *round = 0;
      LOG_D(PHY,"process %d is first free process\n", *harq_pid);
    }

304 305
    LOG_D(PHY,"get_ue_active_harq_pid DL => Frame %d, Subframe %d : harq_pid %d\n",
	  frame,subframe,*harq_pid);
306
  } else { // This is a UL request
307

308 309 310
    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);
311
    // Note this is for TDD configuration 3,4,5 only
312
    *harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,
313 314
                                  ulsch_frame,
                                  ulsch_subframe);
315
    *round    = ULSCH_ptr->harq_processes[*harq_pid]->round;
316
    LOG_T(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Checking HARQ, round %d\n",Mod_id,*harq_pid,frame,subframe,*round);
317
  }
318

319 320 321
  return(0);
}

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

327 328
int16_t get_target_pucch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
{
329
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
330 331
}

332
#ifdef EMOS
333
void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB)
334
{
335 336 337 338 339 340

}
#endif



341
void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type)
342 343
{
  UNUSED(r_type);
344
  int subframe = proc->subframe_rx;
345

346
#ifdef DEBUG_PHY_PROC
347
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", eNB->Mod_id,proc->frame_rx, subframe);
348
#endif
349

350

Raymond Knopp's avatar
 
Raymond Knopp committed
351
  if (abstraction_flag == 0) {
352
    lte_eNB_I0_measurements(eNB,
353
			    subframe,
354
                            0,
355
                            eNB->first_run_I0_measurements);
Raymond Knopp's avatar
 
Raymond Knopp committed
356
  }
357

358
#ifdef PHY_ABSTRACTION
Raymond Knopp's avatar
 
Raymond Knopp committed
359
  else {
360
    lte_eNB_I0_measurements_emul(eNB,
361
                                 0);
362
  }
363

Raymond Knopp's avatar
 
Raymond Knopp committed
364 365
#endif

366

367 368
}

Raymond Knopp's avatar
 
Raymond Knopp committed
369 370


371
#ifdef EMOS
372
void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *eNB)
373 374
{

375 376
  uint8_t aa;
  uint16_t last_subframe_emos;
377
  uint16_t pilot_pos1 = 3 - eNB->frame_parms.Ncp, pilot_pos2 = 10 - 2*eNB->frame_parms.Ncp;
378
  uint32_t bytes;
379 380 381

  last_subframe_emos=0;

Raymond Knopp's avatar
 
Raymond Knopp committed
382

Raymond Knopp's avatar
 
Raymond Knopp committed
383

Raymond Knopp's avatar
 
Raymond Knopp committed
384

385
#ifdef EMOS_CHANNEL
386

387
  //if (last_slot%2==1) // this is for all UL subframes
388
  if (subframe==3)
389 390 391 392 393 394 395
    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));
396
    }
397

398 399
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
400
  if (subframe==4) {
401
    emos_dump_eNB.timestamp = rt_get_time_ns();
402 403 404 405 406
    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],
407
           sizeof(PHY_MEASUREMENTS_eNB));
408
    memcpy(&emos_dump_eNB.UE_stats[0],&eNB->UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats));
409 410

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

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


#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
#define AMP_OVER_2 (AMP>>1)
429 430
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)};
431

Lionel Gauthier's avatar
Lionel Gauthier committed
432

Raymond Knopp's avatar
 
Raymond Knopp committed
433

Cedric Roux's avatar
Cedric Roux committed
434
unsigned int taus(void);
Raymond Knopp's avatar
 
Raymond Knopp committed
435

436
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) {
437

438
#ifdef Rel10
439 440
  MCH_PDU *mch_pduP;
  MCH_PDU  mch_pdu;
441
  //  uint8_t sync_area=255;
442
#endif
443
  int subframe = proc->subframe_tx;
444

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

516
void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstraction_flag) {
517

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

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
  // generate Cell-Specific Reference Signals for both slots
  if (abstraction_flag==0) {
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
			 subframe<<1,0);
    // check that 2nd slot is for DL
    if (subframe_select(fp,subframe) == SF_DL)
      generate_pilots_slot(eNB,
			   txdataF,
			   AMP,
			   (subframe<<1)+1,0);
    
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0);
  }    
Raymond Knopp's avatar
 
Raymond Knopp committed
540

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

635
    /// generate PBCH
Raymond Knopp's avatar
 
Raymond Knopp committed
636
    if (abstraction_flag==0) {
637
      generate_pbch(&eNB->pbch,
638 639 640 641
                    txdataF,
                    AMP,
                    fp,
                    pbch_pdu,
642
                    frame&3);
643 644 645 646 647 648
    }
#ifdef PHY_ABSTRACTION
    else {
      generate_pbch_emul(eNB,pbch_pdu);
    }
#endif
649

650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
  }
  else if ((subframe == 1) &&
	   (fp->frame_type == TDD)&&
	   (abstraction_flag==0)) {
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
  }
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
	   (fp->frame_type == FDD) &&
	   (abstraction_flag==0)) {
        generate_pss(txdataF,
666
                     AMP,
667
                     &eNB->frame_parms,
668 669 670 671
                     (fp->Ncp==NORMAL) ? 6 : 5,
                     10);
        generate_sss(txdataF,
                     AMP,
672
                     &eNB->frame_parms,
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
                     (fp->Ncp==NORMAL) ? 5 : 4,
                     10);

  }

  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
	   (fp->frame_type == TDD) &&
	   (abstraction_flag==0)) {
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
  }

  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
	   (fp->frame_type == TDD) &&
	   (abstraction_flag==0)) {
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }

}

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

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

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

    
    if (UE_id>=0) {
#if defined(SMBV) 
      // Configure this user
784 785
      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,
786 787 788 789 790 791 792 793 794 795 796 797
              dci_alloc->rnti,eNB->transmission_mode[(uint8_t)UE_id]);
	smbv_configure_user(smbv_fname,UE_id+1,eNB->transmission_mode[(uint8_t)UE_id],dci_alloc->rnti);
      }
      
#endif

      LOG_D(PHY,"Generating dlsch params for RNTI %x\n",dci_alloc->rnti);      
      generate_eNB_dlsch_params_from_dci(frame,
					 subframe,
					 &dci_alloc->dci_pdu[0],
					 dci_alloc->rnti,
					 dci_alloc->format,
798
					 eNB->dlsch[(uint8_t)UE_id],
799 800 801 802 803
					 fp,
					 eNB->pdsch_config_dedicated,
					 SI_RNTI,
					 0,
					 P_RNTI,
804
					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single);
805
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
806
	    eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
807 808
      
      
809
      eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
810
      
811
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"/%u\n",eNB->Mod_id,frame,subframe,
812
	    dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]);
813 814 815 816
      
#if defined(SMBV) 
      
      // configure UE-spec DCI
817 818
      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);
819
	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
820
      }
821 822 823 824 825
      
#endif
      
      LOG_D(PHY,"[eNB %"PRIu8"][DCI][PDSCH %"PRIx16"] Frame %d subframe %d UE_id %"PRId8" Generated DCI format %d, aggregation %d\n",
	    eNB->Mod_id, dci_alloc->rnti,
826
	    frame, subframe,UE_id,
827 828 829 830
	    dci_alloc->format,
	    1<<dci_alloc->L);
    } else {
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH] Frame %d : No UE_id with corresponding rnti %"PRIx16", dropping DLSCH\n",
831
	    eNB->Mod_id,frame,dci_alloc->rnti);
Raymond Knopp's avatar
 
Raymond Knopp committed
832
    }
833 834 835
  }
  
}
836

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

839
  int harq_pid;
840
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
841
  int frame = proc->frame_tx;
Raymond Knopp's avatar
Raymond Knopp committed
842
  int subframe = proc->subframe_tx;
843

Raymond Knopp's avatar
Raymond Knopp committed
844
  LOG_I(PHY,
845 846 847
	"[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,
848
			  pdcch_alloc2ul_frame(fp,frame,subframe),
849
			  pdcch_alloc2ul_subframe(fp,subframe)),
850
	frame,
851
	subframe,
852
	pdcch_alloc2ul_frame(fp,frame,subframe),
853 854 855 856 857
	pdcch_alloc2ul_subframe(fp,subframe),
	dci_alloc->rnti,
	dci_alloc->dci_pdu[0],
	1<<dci_alloc->L);
  
858
  generate_eNB_ulsch_params_from_dci(eNB,
859
				     proc,
860
				     &dci_alloc->dci_pdu[0],
861 862 863 864 865 866 867 868 869 870
				     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",
871
	eNB->Mod_id,frame,subframe,dci_alloc->rnti,
872 873 874 875 876
	dci_alloc->firstCCE);
  
#if defined(SMBV) 
  
  // configure UE-spec DCI for UL Grant
877 878
  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);
879 880 881 882 883 884 885 886
    smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i);
  }
  
#endif
  
  
  // get the hard_pid for this subframe 
  harq_pid = subframe2harq_pid(fp,
887
			       pdcch_alloc2ul_frame(fp,frame,subframe),
888 889 890
			       pdcch_alloc2ul_subframe(fp,subframe));
  
  if (harq_pid==255) { // should not happen, log an error and exit, this is a fatal error
891
    LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Bad harq_pid for ULSCH allocation\n",eNB->Mod_id,frame);
892 893 894 895
    mac_xface->macphy_exit("FATAL\n"); 
  }
  
  if ((dci_alloc->rnti  >= CBA_RNTI) && (dci_alloc->rnti < P_RNTI))
896
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag = 1;
897
  else
898
    eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
899 900
  
}
901

902
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,int abstraction_flag) {
903

904 905
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
906 907 908
  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;
909
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
910 911 912 913 914 915 916 917
  uint8_t *DLSCH_pdu=NULL;
  uint8_t DLSCH_pdu_tmp[768*8];
  uint8_t DLSCH_pdu_rar[256];
  int i;

  LOG_D(PHY,
	"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n",
	eNB->Mod_id, dlsch->rnti,harq_pid,
918
	frame, subframe, input_buffer_length,
919 920 921 922 923
	get_G(fp,
	      dlsch_harq->nb_rb,
	      dlsch_harq->rb_alloc,
	      get_Qm(dlsch_harq->mcs),
	      dlsch_harq->Nl,
924
	      num_pdcch_symbols,frame,subframe),
925 926 927 928 929
	dlsch_harq->nb_rb,
	dlsch_harq->mcs,
	pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	dlsch_harq->rvidx,
	dlsch_harq->round);
930

931 932 933 934 935
#if defined(MESSAGE_CHART_GENERATOR_PHY)
      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")",
936
        frame, subframe,
937 938 939 940 941 942
        input_buffer_length,
        get_G(fp,
        		dlsch_harq->nb_rb,
        		dlsch_harq->rb_alloc,
        		get_Qm(dlsch_harq->mcs),
        		dlsch_harq->Nl,
943
        		num_pdcch_symbols,frame,subframe),
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
        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]++;

	if (eNB->mac_enabled==1) {
	  if (ra_flag == 0) {
	    DLSCH_pdu = mac_xface->get_dlsch_sdu(eNB->Mod_id,
						 eNB->CC_id,
962
						 frame,
963 964 965 966 967 968
						 dlsch->rnti,
						 0);
	  }
	  else {
	    int16_t crnti = mac_xface->fill_rar(eNB->Mod_id,
						eNB->CC_id,
969
						frame,
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985
						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;
	    
	    if (UE_id==-1) {
	      LOG_W(PHY,"[eNB] Max user count reached.\n");
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
986
					frame,
987 988
					crnti);
	    } else {
989
	      eNB->UE_stats[(uint32_t)UE_id].mode = RA_RESPONSE;
990 991 992 993
	      // Initialize indicator for first SR (to be cleared after ConnectionSetup is acknowledged)
	      eNB->first_sr[(uint32_t)UE_id] = 1;
	      
	      generate_eNB_ulsch_params_from_rar(DLSCH_pdu,
994
						 frame,
995
						 (subframe),
996
						 eNB->ulsch[(uint32_t)UE_id],
997 998
						 fp);
	      
999
	      eNB->ulsch[(uint32_t)UE_id]->Msg3_active = 1;
1000 1001 1002
	      
	      get_Msg3_alloc(fp,
			     subframe,
1003
			     frame,
1004 1005
			     &eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
			     &eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
1006
	      LOG_D(PHY,"[eNB][RAPROC] Frame %d subframe %d, Activated Msg3 demodulation for UE %"PRId8" in frame %"PRIu32", subframe %"PRIu8"\n",
1007
		    frame,
1008 1009
		    subframe,
		    UE_id,
1010 1011
		    eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
		    eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
	    }
	    if (ue_stats) ue_stats->total_TBS_MAC += dlsch_harq->TBS;
	  }
	}
	else {
	  DLSCH_pdu = DLSCH_pdu_tmp;
	  
	  for (i=0; i<input_buffer_length; i++)
	    DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
	}
	
#if defined(SMBV) 
1024

1025
        // Configures the data source of allocation (allocation is configured by DCI)
1026 1027
        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);
1028
	  //          smbv_configure_datalist_for_user(smbv_fname, find_ue(dlsch->rnti,eNB)+1, DLSCH_pdu, input_buffer_length);
1029
        }
1030

1031
#endif
1032

1033 1034 1035 1036 1037 1038 1039 1040 1041

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

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

        LOG_T(PHY,"\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
1042
#endif
1043 1044 1045 1046 1047 1048 1049 1050 1051
#endif
      } else {
        ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++;
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
        LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
#endif
#endif
      }
1052

1053
      if (abstraction_flag==0) {
1054

1055 1056 1057 1058 1059 1060 1061
	LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag);
        // 36-212
        start_meas(&eNB->dlsch_encoding_stats);
        dlsch_encoding(DLSCH_pdu,
                       fp,
                       num_pdcch_symbols,
                       dlsch,
1062
                       frame,subframe,
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
                       &eNB->dlsch_rate_matching_stats,
                       &eNB->dlsch_turbo_encoding_stats,
                       &eNB->dlsch_interleaving_stats);
        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,
1077
                               num_pdcch_symbols,frame,subframe),
1078 1079 1080 1081
                         0,
                         subframe<<1);
        stop_meas(&eNB->dlsch_scrambling_stats);
        start_meas(&eNB->dlsch_modulation_stats);
1082 1083


1084
        dlsch_modulation(eNB->common_vars.txdataF[0],
1085 1086 1087 1088 1089 1090 1091 1092 1093
			 AMP,
			 subframe,
			 fp,
			 num_pdcch_symbols,
			 dlsch,
			 dlsch1);
	
        stop_meas(&eNB->dlsch_modulation_stats);
      }
1094

1095 1096 1097 1098 1099 1100 1101
#ifdef PHY_ABSTRACTION
      else {
        start_meas(&eNB->dlsch_encoding_stats);
        dlsch_encoding_emul(eNB,
                            DLSCH_pdu,
                            dlsch);
        stop_meas(&eNB->dlsch_encoding_stats);
Raymond Knopp's avatar
 
Raymond Knopp committed
1102
      }
1103

1104 1105 1106
#endif
      dlsch->active = 0;
}
1107

1108
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
1109
			   eNB_rxtx_proc_t *proc,
1110 1111 1112 1113 1114
			   uint8_t abstraction_flag,
                           relaying_type_t r_type,
			   PHY_VARS_RN *rn)
{
  UNUSED(rn);
1115 1116
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
1117
  //  uint16_t input_buffer_length;
1118 1119 1120 1121
  uint32_t i,aa;
  uint8_t harq_pid;
  DCI_PDU *DCI_pdu;
  DCI_PDU DCI_pdu_tmp;
1122
  int8_t UE_id=0;
1123 1124 1125
  uint8_t num_pdcch_symbols=0;
  uint8_t ul_subframe;
  uint32_t ul_frame;
1126
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1127
  DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL;
1128

1129 1130 1131 1132 1133
#if defined(SMBV) 
  // counts number of allocations in subframe
  // there is at least one allocation for PDCCH
  uint8_t smbv_alloc_cnt = 1;
#endif
1134

1135 1136
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,1);
  start_meas(&eNB->phy_proc_tx);
1137

1138 1139
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    // If we've dropped the UE, go back to PRACH mode for this UE
1140

1141
    if (eNB->UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) {
1142
      LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n",
1143 1144
            eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->UE_stats[i].ulsch_consecutive_errors);
      eNB->UE_stats[i].ulsch_consecutive_errors=0;
1145 1146 1147
      mac_xface->UL_failure_indication(eNB->Mod_id,
				       eNB->CC_id,
				       frame,
1148
				       eNB->UE_stats[i].crnti,
1149 1150
				       subframe);
				       
Raymond Knopp's avatar
 
Raymond Knopp committed
1151
    }
1152
	
1153

1154
  }
1155 1156


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

1165 1166 1167
// clear the transmit data array for the current subframe
  if (abstraction_flag==0) {
    for (aa=0; aa<fp->nb_antennas_tx_eNB; aa++) {      
1168
      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
1169 1170 1171
             0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
    }
  }
1172

1173
  if (is_pmch_subframe(frame,subframe,fp)) {
1174
    pmch_procedures(eNB,proc,rn,abstraction_flag,r_type);
1175 1176 1177
  }
  else {
    // this is not a pmch subframe, so generate PSS/SSS/PBCH
1178
    common_signal_procedures(eNB,proc,abstraction_flag);
1179
  }
1180

1181
#if defined(SMBV) 
1182

Raymond Knopp's avatar
 
Raymond Knopp committed
1183
  // PBCH takes one allocation
1184
  if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
1185
    if (subframe==0)
Raymond Knopp's avatar
 
Raymond Knopp committed
1186 1187
      smbv_alloc_cnt++;
  }
1188

1189
#endif
1190

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

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

1212 1213 1214
  if ((subframe_select(fp,ul_subframe)==SF_UL) ||
      (fp->frame_type == FDD)) {
    harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
1215

1216
    // clear DCI allocation maps for new subframe
1217
    for (i=0; i<NUMBER_OF_UE_MAX; i++)
1218 1219 1220
      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
1221 1222
      }
  }
1223

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


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

1234
#if defined(SMBV) 
Raymond Knopp's avatar
 
Raymond Knopp committed
1235
  // Sets up PDCCH and DCI table
1236 1237
  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);
1238
    dump_dci(fp,&DCI_pdu->dci_alloc[0]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1239 1240
    smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
  }
1241 1242
#endif

1243 1244
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);

1245
  // loop over all DCIs for this subframe to generate DLSCH allocations
1246 1247 1248 1249 1250
  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);
1251
    dci_alloc = &DCI_pdu->dci_alloc[i];
1252

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1264
  }
1265

1266 1267
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

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

1288 1289


Lionel Gauthier's avatar
Lionel Gauthier committed
1290 1291


Raymond Knopp's avatar
 
Raymond Knopp committed
1292 1293
  // 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
1294

1295 1296

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1301
  if (abstraction_flag == 0) {
1302

Raymond Knopp's avatar
 
Raymond Knopp committed
1303
    if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0)
1304
      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,
1305 1306 1307 1308 1309 1310 1311
            DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1316
  }
1317

1318
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
Raymond Knopp's avatar
 
Raymond Knopp committed
1319
  else {
1320
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
1321
    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
1322
  }
1323

1324 1325
#endif

1326
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
1327

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

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

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

1334
#if defined(SMBV) 
1335

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

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

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

1348
#if defined(SMBV) 
1349

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

1378
      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,abstraction_flag);
1379 1380


Raymond Knopp's avatar
 
Raymond Knopp committed
1381
    }
Lionel Gauthier's avatar
Lionel Gauthier committed
1382

1383 1384 1385
    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)) {
1386

Raymond Knopp's avatar
 
Raymond Knopp committed
1387
      // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
1388
      eNB->dlsch[(uint8_t)UE_id][0]->subframe_tx[subframe]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1389
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1390
  }
1391

1392 1393


Raymond Knopp's avatar
 
Raymond Knopp committed
1394
  // if we have PHICH to generate
1395

1396
  if (is_phich_subframe(fp,subframe))
1397
  {
1398
    generate_phich_top(eNB,
1399
		       proc,
1400 1401 1402
                       AMP,
                       0,
                       abstraction_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
1403
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1404

1405 1406


1407
#ifdef EMOS
1408
  phy_procedures_emos_eNB_TX(subframe, eNB);
1409
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
1410

1411
#if !(defined(EXMIMO) || defined(OAI_USRP) || defined (CPRIGW))
1412 1413 1414

  if (abstraction_flag==0)
  {
1415
    start_meas(&eNB->ofdm_mod_stats);
1416 1417
    do_OFDM_mod(eNB->common_vars.txdataF[0],
                eNB->common_vars.txdata[0],
1418
                frame,subframe<<1,
1419
                fp);
1420 1421
    do_OFDM_mod(eNB->common_vars.txdataF[0],
                eNB->common_vars.txdata[0],
1422
                frame,1+(subframe<<1),
1423 1424
                fp);
    stop_meas(&eNB->ofdm_mod_stats);
Raymond Knopp's avatar
 
Raymond Knopp committed
1425
  }
1426

Raymond Knopp's avatar
 
Raymond Knopp committed
1427
#endif
1428

1429
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,0);
1430
  stop_meas(&eNB->phy_proc_tx);
1431 1432


1433 1434
}

1435
void process_Msg3(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id, uint8_t harq_pid)
1436
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1437
  // this prepares the demodulation of the first PUSCH of a new user, containing Msg3
1438 1439
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;
Raymond Knopp's avatar
 
Raymond Knopp committed
1440

Raymond Knopp's avatar
 
Raymond Knopp committed
1441
  LOG_D(PHY,"[eNB %d][RAPROC] frame %d : subframe %d : process_Msg3 UE_id %d (active %d, subframe %d, frame %d)\n",
1442
        eNB->Mod_id,
1443
        frame,subframe,
1444 1445 1446 1447
        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;
1448

1449 1450 1451
  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))   {
1452

1453
    //    harq_pid = 0;
1454

1455 1456 1457
    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
1458
    LOG_D(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Setting subframe_scheduling_flag (Msg3) for UE %d\n",
1459
          eNB->Mod_id,
1460
          frame,subframe,UE_id);
1461 1462 1463 1464 1465 1466 1467 1468 1469
  }
}


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

1470
void process_HARQ_feedback(uint8_t UE_id,
1471
                           PHY_VARS_eNB *eNB,
1472
			   eNB_rxtx_proc_t *proc,
1473 1474 1475 1476 1477
                           uint8_t pusch_flag,
                           uint8_t *pucch_payload,
                           uint8_t pucch_sel,
                           uint8_t SR_payload)
{
1478

1479
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1480
  uint8_t dl_harq_pid[8],dlsch_ACK[8],dl_subframe;
1481 1482
  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];
1483
  LTE_DL_eNB_HARQ_t *dlsch_harq_proc;
1484
  uint8_t subframe_m4,M,m;
1485 1486
  int mp;
  int all_ACKed=1,nb_alloc=0,nb_ACK=0;
1487 1488
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1489
  int harq_pid = subframe2harq_pid( fp,frame,subframe);
1490

1491 1492

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

1495 1496
    dl_harq_pid[0] = dlsch->harq_ids[subframe_m4];
    M=1;
1497

1498
    if (pusch_flag == 1) {
1499
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1500
      if (dlsch->subframe_tx[subframe_m4]==1)
1501
      LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUSCH for subframe %d\n",eNB->Mod_id,
1502 1503 1504
	    frame,dlsch_ACK[0],subframe_m4);
    }
    else {
1505
      dlsch_ACK[0] = pucch_payload[0];
1506
      LOG_D(PHY,"[eNB %d] Frame %d: Received ACK/NAK %d on PUCCH for subframe %d\n",eNB->Mod_id,
1507
	    frame,dlsch_ACK[0],subframe_m4);
kaltenbe's avatar
kaltenbe committed
1508
      /*
1509 1510
      if (dlsch_ACK[0]==0)
	AssertFatal(0,"Exiting on NAK on PUCCH\n");
kaltenbe's avatar
kaltenbe committed
1511
      */
1512
    }
1513

Lionel Gauthier's avatar
Lionel Gauthier committed
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527

#if defined(MESSAGE_CHART_GENERATOR_PHY)
    MSC_LOG_RX_MESSAGE(
      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
      );
#endif
1528 1529
  } else { // TDD Handle M=1,2 cases only

1530
    M=ul_ACK_subframe2_M(fp,
1531 1532
                         subframe);

1533 1534 1535 1536 1537 1538 1539 1540
    // 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

1541
      dlsch_ACK[0] = eNB->ulsch[(uint8_t)UE_id]->harq_processes[harq_pid]->o_ACK[0];
1542
      dlsch_ACK[1] = (eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode == bundling)
1543
                     ?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];
1544
    }
1545

1546
    else {  // PUCCH ACK/NAK
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581
      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;
        }
1582
      }
1583
    }
1584 1585 1586 1587
  }

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

    for (m=0; m<M; m++) {
1591
      dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1592 1593 1594 1595 1596
                    subframe,
                    m);

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

1599 1600
    if (nb_alloc == nb_ACK)
      all_ACKed = 1;
1601
    else
1602
      all_ACKed = 0;
1603 1604 1605
  }


1606
  for (m=0,mp=-1; m<M; m++) {
1607

1608
    dl_subframe = ul_ACK_subframe2_dl_subframe(fp,
1609 1610
                  subframe,
                  m);
1611

1612 1613
    if (dlsch->subframe_tx[dl_subframe]==1) {
      if (pusch_flag == 1)
1614
        mp++;
1615
      else
1616
        mp = m;
1617

1618
      dl_harq_pid[m]     = dlsch->harq_ids[dl_subframe];
1619

1620
      if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
1621 1622 1623 1624
        if ((SR_payload == 1)&&(all_ACKed == 1))
          dlsch_ACK[m] = 1;
        else
          dlsch_ACK[m] = 0;
1625
      }
1626

1627
      if (dl_harq_pid[m]<dlsch->Mdlharq) {
1628 1629
        dlsch_harq_proc = dlsch->harq_processes[dl_harq_pid[m]];
#ifdef DEBUG_PHY_PROC
1630
        LOG_D(PHY,"[eNB %d][PDSCH %x/%d] subframe %d, status %d, round %d (mcs %d, rv %d, TBS %d)\n",eNB->Mod_id,
1631 1632 1633 1634 1635 1636 1637 1638 1639
              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");

1640
#endif
1641 1642 1643 1644 1645 1646 1647 1648

        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
1649
            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,
1650
                  dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
1651
#endif
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661

            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++;

1662

1663
            if (dlsch_harq_proc->round == dlsch->Mlimit) {
1664 1665
              // This was the last round for DLSCH so reset round and increment l2_error counter
#ifdef DEBUG_PHY_PROC
1666
              LOG_W(PHY,"[eNB %d][PDSCH %x/%d] DLSCH retransmissions exhausted, dropping packet\n",eNB->Mod_id,
1667
                    dlsch->rnti,dl_harq_pid[m]);
1668
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1669
#if defined(MESSAGE_CHART_GENERATOR_PHY)
1670
              MSC_LOG_EVENT(MSC_PHY_ENB, "0 HARQ DLSCH Failed RNTI %"PRIx16" round %u",
1671 1672
                            dlsch->rnti,
                            dlsch_harq_proc->round);
Lionel Gauthier's avatar
Lionel Gauthier committed
1673
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1674

1675 1676 1677
              dlsch_harq_proc->round = 0;
              ue_stats->dlsch_l2_errors[dl_harq_pid[m]]++;
              dlsch_harq_proc->status = SCH_IDLE;
1678
              put_harq_pid_in_freelist(dlsch, dl_harq_pid[m]);
1679 1680 1681 1682
              dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq;
            }
          } else {
#ifdef DEBUG_PHY_PROC
1683
            LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
1684
                  dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
1685
#endif
1686 1687 1688 1689 1690
            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;
1691
            put_harq_pid_in_freelist(dlsch, dl_harq_pid[m]);
1692 1693 1694
            dlsch->harq_ids[dl_subframe] = dlsch->Mdlharq;

            ue_stats->total_TBS = ue_stats->total_TBS +
1695
                                  eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1696 1697
            /*
              ue_stats->total_transmitted_bits = ue_stats->total_transmitted_bits +
1698
              eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
            */
          }

          // 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);
1713
#endif
1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735

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


        }
1736
      }
1737
    }
1738 1739 1740
  }
}

1741
void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
1742
		      eNB_rxtx_proc_t *proc,
1743 1744 1745 1746 1747 1748
                      uint8_t UE_id,
                      int16_t *n1_pucch0,
                      int16_t *n1_pucch1,
                      int16_t *n1_pucch2,
                      int16_t *n1_pucch3)
{
1749

1750
  LTE_DL_FRAME_PARMS *frame_parms=&eNB->frame_parms;
1751
  uint8_t nCCE0,nCCE1;
1752
  int sf;
1753 1754
  int frame = proc->frame_rx;
  int subframe = proc->subframe_rx;
1755 1756

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

1759 1760
    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];
1761
      *n1_pucch1 = -1;
1762
    } else {
1763 1764 1765
      *n1_pucch0 = -1;
      *n1_pucch1 = -1;
    }
1766
  } else {
1767

1768 1769 1770
    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
1771 1772
        /*  if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
1773 1774 1775 1776 1777
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
          }
          else
          *n1_pucch1 = -1;*/

1778 1779
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[5]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[5];
1780 1781 1782 1783 1784 1785 1786
          *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

1787 1788
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1789 1790 1791 1792 1793 1794 1795 1796 1797
          *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;
1798 1799
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1800 1801 1802 1803 1804 1805 1806
          *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;
1807 1808
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[4]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[4];
1809 1810 1811 1812 1813 1814 1815
          *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",
1816
              eNB->Mod_id,
1817 1818 1819
              frame,
              subframe,frame_parms->tdd_config);
        return;
1820
      }
1821

1822
      break;
1823

1824 1825
    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)
1826 1827
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[6]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[6];
1828 1829 1830 1831
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

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

1841 1842
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[8]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[8];
1843 1844 1845 1846 1847
          *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;

1848 1849
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[7]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[7];
1850 1851 1852 1853 1854
          *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
1855 1856
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[0]>0) {
          nCCE1 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[0];
1857 1858 1859 1860
          *n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch1 = -1;

1861 1862
        if (eNB->dlsch[(uint32_t)UE_id][0]->subframe_tx[9]>0) {
          nCCE0 = eNB->dlsch[(uint32_t)UE_id][0]->nCCE[9];
1863 1864 1865 1866 1867
          *n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0 +frame_parms->pucch_config_common.n1PUCCH_AN;
        } else
          *n1_pucch0 = -1;
      } else {
        LOG_D(PHY,"[eNB %d] Frame %d: phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n",
1868
              eNB->Mod_id,frame,subframe,frame_parms->tdd_config);
1869
        return;
1870
      }
1871

1872
      break;
1873 1874
    }  // switch tdd_config

1875 1876 1877
    // Don't handle the case M>2
    *n1_pucch2 = -1;
    *n1_pucch3 = -1;
1878 1879 1880
  }
}

1881
void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag)
1882
{
1883

1884
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
1885 1886 1887 1888
  uint16_t preamble_energy_list[64],preamble_delay_list[64];
  uint16_t preamble_max,preamble_energy_max;
  uint16_t i;
  int8_t UE_id;
1889 1890
  int subframe = eNB->proc.subframe_prach;
  int frame = eNB->proc.frame_prach;
1891
  uint8_t CC_id = eNB->CC_id;
1892

1893 1894
  memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
  memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
1895

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

1900

1901
    rx_prach(eNB,
1902 1903 1904 1905 1906 1907 1908
             preamble_energy_list,
             preamble_delay_list,
             frame,
             0);
  } else {
    for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {

1909
      LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
1910
            UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
1911
            PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
1912
            fp->prach_config_common.rootSequenceIndex,
1913 1914
            PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex);

Raymond Knopp's avatar
 
Raymond Knopp committed
1915
      if ((PHY_vars_UE_g[UE_id][CC_id]->generate_prach==1) &&
1916
          (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex ==
1917
           fp->prach_config_common.rootSequenceIndex) ) {
1918 1919 1920
        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;

1921
      }
1922
    }
1923
  }
1924

1925 1926 1927
  preamble_energy_max = preamble_energy_list[0];
  preamble_max = 0;

1928
  for (i=1; i<64; i++) {
1929 1930 1931 1932
    if (preamble_energy_max < preamble_energy_list[i]) {
      preamble_energy_max = preamble_energy_list[i];
      preamble_max = i;
    }
1933 1934 1935
  }

#ifdef DEBUG_PHY_PROC
1936
  LOG_D(PHY,"[RAPROC] Most likely preamble %d, energy %d dB delay %d\n",
1937 1938 1939
        preamble_max,
        preamble_energy_list[preamble_max],
        preamble_delay_list[preamble_max]);
1940 1941
#endif

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

1944
    UE_id = find_next_ue_index(eNB);
1945
 
1946
    if (UE_id>=0) {
1947
      eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
1948

1949
      eNB->UE_stats[(uint32_t)UE_id].sector = 0;
1950
      LOG_I(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",
1951 1952
            eNB->Mod_id,
            eNB->CC_id,
1953 1954
            frame,
            subframe,
1955
	    UE_id,
1956 1957 1958 1959
            preamble_max,
            preamble_energy_max/10,
            preamble_energy_max%10,
            preamble_delay_list[preamble_max]);
1960

1961
      if (eNB->mac_enabled==1) {
1962 1963
        uint8_t update_TA=4;

1964
        switch (fp->N_RB_DL) {
1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981
        case 6:
          update_TA = 16;
          break;

        case 25:
          update_TA = 4;
          break;

        case 50:
          update_TA = 2;
          break;

        case 100:
          update_TA = 1;
          break;
        }

1982 1983
      mac_xface->initiate_ra_proc(eNB->Mod_id,
                                  eNB->CC_id,
1984 1985
                                  frame,
                                  preamble_max,
1986
                                  preamble_delay_list[preamble_max]*update_TA,
Raymond Knopp's avatar
 
Raymond Knopp committed
1987
				  0,subframe,0);
1988 1989
      }      

1990
    } else {
1991
      MSC_LOG_EVENT(MSC_PHY_ENB, "0 RA Failed add user, too many");
1992
      LOG_I(PHY,"[eNB %d][RAPROC] frame %d, subframe %d: Unable to add user, max user count reached\n",
1993
            eNB->Mod_id,frame, subframe);
1994
    }
1995 1996 1997
  }
}

1998
void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1999

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

2011 2012 2013
  if ((eNB->dlsch[UE_id][0]) &&
      (eNB->dlsch[UE_id][0]->rnti>0) &&
      (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag==0)) { 
2014

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

2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079
	if (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,
				subframe,
				PUCCH1_THRES);
	
2080
#ifdef PHY_ABSTRACTION
2081 2082 2083 2084 2085 2086 2087 2088 2089 2090
	else {
	  metric0_SR = rx_pucch_emul(eNB,
				     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);
	}
	
2091
#endif
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114
	
	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
	    /* is this test necessary? */
	    if (eNB->dlsch[UE_id][0]->harq_processes[0]->status != SCH_IDLE)
	      put_harq_pid_in_freelist(eNB->dlsch[UE_id][0], 0);
	    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);
2115
	  }
2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151
	}
      }// do_SR==1
      
      if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR
      } else if (fp->frame_type==FDD) { // FDD
	// if SR was detected, use the n1_pucch from SR, else use n1_pucch0
	//          n1_pucch0 = (SR_payload==1) ? eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex:n1_pucch0;
	
	LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload);
	
	if (abstraction_flag == 0) {
	  
	  
	  
	  metric0 = rx_pucch(eNB,
			     pucch_format1a,
			     UE_id,
			     (uint16_t)n1_pucch0,
			     0, //n2_pucch
			     0, // shortened format
			     pucch_payload0,
			     subframe,
			     PUCCH1a_THRES);
	  
	  if (metric0 < metric0_SR)
	    metric0=rx_pucch(eNB,
			     pucch_format1a,
			     UE_id,
			     eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
			     0, //n2_pucch
			     0, // shortened format
			     pucch_payload0,
			     subframe,
			     PUCCH1a_THRES);
	}
	else {
2152
#ifdef PHY_ABSTRACTION
2153 2154 2155 2156 2157
	  metric0 = rx_pucch_emul(eNB,UE_id,
				  pucch_format1a,
				  0,
				  pucch_payload0,
				  subframe);
2158
#endif
2159 2160
	}
	
2161
#ifdef DEBUG_PHY_PROC
2162 2163 2164 2165 2166
	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);
2167
#endif
2168 2169
	
	process_HARQ_feedback(UE_id,eNB,proc,
2170 2171 2172 2173
                                0,// pusch_flag
                                pucch_payload0,
                                2,
                                SR_payload);
2174

2175 2176
        } // FDD
        else {  //TDD
2177

2178
          bundling_flag = eNB->pucch_config_dedicated[UE_id].tdd_AckNackFeedbackMode;
2179

2180
          // fix later for 2 TB case and format1b
Raymond Knopp's avatar
Raymond Knopp committed
2181

2182
          if ((fp->frame_type==FDD) ||
2183
              (bundling_flag==bundling)    ||
2184
              ((fp->frame_type==TDD)&&(fp->tdd_config==1)&&((subframe!=2)||(subframe!=7)))) {
2185
            format = pucch_format1a;
2186
	  } else {
2187
            format = pucch_format1b;
2188
	  }
2189

2190 2191 2192
          // if SR was detected, use the n1_pucch from SR
          if (SR_payload==1) {
#ifdef DEBUG_PHY_PROC
2193
            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,
2194
                  eNB->dlsch[UE_id][0]->rnti,
2195 2196 2197
                  frame,subframe,
                  n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
#endif
2198

2199
            if (abstraction_flag == 0)
2200
              metric0_SR = rx_pucch(eNB,
2201 2202
				    format,
				    UE_id,
2203
				    eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,
2204 2205 2206 2207 2208 2209
				    0, //n2_pucch
				    0, // shortened format
				    pucch_payload0,
				    subframe,
				    PUCCH1a_THRES);
            else {
2210
#ifdef PHY_ABSTRACTION
2211
              metric0 = rx_pucch_emul(eNB,UE_id,
2212 2213 2214 2215
                                      format,
                                      0,
                                      pucch_payload0,
                                      subframe);
2216
#endif
2217 2218 2219
            }
          } else { //using n1_pucch0/n1_pucch1 resources
#ifdef DEBUG_PHY_PROC
2220
            LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d\n",eNB->Mod_id,
2221
                  eNB->dlsch[UE_id][0]->rnti,
2222 2223 2224 2225 2226
                  frame,subframe,
                  n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
#endif
            metric0=0;
            metric1=0;
2227

2228 2229 2230
            // Check n1_pucch0 metric
            if (n1_pucch0 != -1) {
              if (abstraction_flag == 0)
2231
                metric0 = rx_pucch(eNB,
2232 2233 2234 2235 2236 2237 2238 2239 2240
                                   format,
                                   UE_id,
                                   (uint16_t)n1_pucch0,
                                   0, // n2_pucch
                                   0, // shortened format
                                   pucch_payload0,
                                   subframe,
                                   PUCCH1a_THRES);
              else {
2241
#ifdef PHY_ABSTRACTION
2242
                metric0 = rx_pucch_emul(eNB,UE_id,
2243 2244 2245 2246
                                        format,
                                        0,
                                        pucch_payload0,
                                        subframe);
2247
#endif
2248 2249
              }
            }
2250

2251 2252 2253
            // Check n1_pucch1 metric
            if (n1_pucch1 != -1) {
              if (abstraction_flag == 0)
2254
                metric1 = rx_pucch(eNB,
2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
                                   format,
                                   UE_id,
                                   (uint16_t)n1_pucch1,
                                   0, //n2_pucch
                                   0, // shortened format
                                   pucch_payload1,
                                   subframe,
                                   PUCCH1a_THRES);
              else {
#ifdef PHY_ABSTRACTION
2265
                metric1 = rx_pucch_emul(eNB,UE_id,
2266 2267 2268 2269
                                        format,
                                        1,
                                        pucch_payload1,
                                        subframe);
2270

2271

2272 2273 2274 2275
#endif
              }
            }
          }
2276

2277 2278
          if (SR_payload == 1) {
            pucch_payload = pucch_payload0;
2279

2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292
            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
          }
2293 2294

#ifdef DEBUG_PHY_PROC
2295
          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,
2296
                eNB->dlsch[UE_id][0]->rnti,
2297 2298
                frame,subframe,
                metric0,metric1,pucch_sel,pucch_payload[0],pucch_payload[1]);
2299
#endif
2300
          process_HARQ_feedback(UE_id,eNB,proc,
2301 2302 2303 2304 2305
                                0,// pusch_flag
                                pucch_payload,
                                pucch_sel,
                                SR_payload);
        }
2306
      }
2307

2308 2309
    }
}
2310

2311
void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) {
2312

2313 2314
  uint8_t access_mode;
  int num_active_cba_groups;
2315 2316
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2317 2318
  uint16_t rnti=0;
  int ret=0;
2319
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2320

2321
  num_active_cba_groups = eNB->ulsch[UE_id]->num_active_cba_groups;
2322
  
2323
  if ((eNB->ulsch[UE_id]) &&
2324
      (num_active_cba_groups > 0) &&
2325 2326
      (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)) {
2327 2328 2329 2330
    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",
2331
	  eNB->Mod_id,harq_pid,
2332
	  frame,subframe,
2333
	  UE_id, (uint16_t)eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->UE_stats[UE_id].mode]);
2334 2335 2336
#endif
    
    if (abstraction_flag==0) {
2337
      rx_ulsch(eNB,proc,
2338
	       eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2339
	       UE_id,
2340
	       eNB->ulsch,
2341 2342 2343 2344 2345
	       0);
    }
    
#ifdef PHY_ABSTRACTION
    else {
2346
      rx_ulsch_emul(eNB,proc,
2347
		    subframe,
2348
		    eNB->UE_stats[UE_id].sector,  // this is the effective sector id
2349
		    UE_id);
2350 2351 2352 2353 2354
    }
    
#endif
    
    if (abstraction_flag == 0) {
2355
      ret = ulsch_decoding(eNB,proc,
2356 2357
			   UE_id,
			   0, // control_only_flag
2358 2359
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->V_UL_DAI,
			   eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2360 2361 2362 2363
    }
    
#ifdef PHY_ABSTRACTION
    else {
2364
      ret = ulsch_decoding_emul(eNB,
2365 2366 2367 2368 2369 2370
				UE_id,
				&rnti);
    }
    
#endif
    
2371
    if (eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2372 2373
#ifdef DEBUG_PHY_PROC
      
2374
      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);
2375 2376
#endif
      access_mode = UNKNOWN_ACCESS;
2377 2378 2379
      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],
2380
		  fp->N_RB_DL,
2381
		  &rnti, &access_mode);
2382
      eNB->UE_stats[UE_id].rank = eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_RI[0];
2383 2384
    }
    
2385 2386
      eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag=0;
      eNB->ulsch[UE_id]->harq_processes[harq_pid]->status= SCH_IDLE;
2387 2388 2389
      
      if ((num_active_cba_groups > 0) &&
          (UE_id + num_active_cba_groups < NUMBER_OF_UE_MAX) &&
2390 2391
          (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)) {
2392 2393
#ifdef DEBUG_PHY_PROC
        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",
2394
              eNB->Mod_id,harq_pid,frame,subframe,UE_id,harq_pid,
2395
              UE_id+num_active_cba_groups, UE_id%eNB->ulsch[UE_id]->num_active_cba_groups);
2396
#endif
2397 2398 2399
        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;
2400
      }
2401

2402
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
2403 2404 2405 2406
        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++;
2407 2408 2409
      } // ulsch in error
      else {
        LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
2410
              eNB->Mod_id,harq_pid,
2411
              frame,subframe);
2412

2413 2414 2415 2416
        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;
2417 2418 2419 2420
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_ULSCH
        LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",
              frame,subframe,
2421
              harq_pid,eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3);
2422

2423 2424
        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]);
2425 2426 2427 2428 2429 2430 2431

        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",
2432
                eNB->Mod_id, frame,subframe,
2433 2434
                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]);
2435

2436
          // detect if there is a CBA collision
2437 2438 2439
          if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) {
            mac_xface->rx_sdu(eNB->Mod_id,
                              eNB->CC_id,
2440
                              frame,subframe,
2441 2442 2443
                              eNB->ulsch[UE_id]->rnti,
                              eNB->ulsch[UE_id]->harq_processes[harq_pid]->b,
                              eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3,
2444 2445 2446
                              harq_pid,
                              NULL);

2447
            eNB->cba_last_reception[UE_id%num_active_cba_groups]+=1;//(subframe);
2448
          } else {
2449
            if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 1 )
2450
              LOG_N(PHY,"[eNB%d] Frame %d subframe %d : first CBA collision detected \n ",
2451
                    eNB->Mod_id,frame,subframe);
2452

2453
            LOG_N(PHY,"[eNB%d] Frame %d subframe %d : CBA collision set SR for UE %d in group %d \n ",
2454 2455
                  eNB->Mod_id,frame,subframe,
                  eNB->cba_last_reception[UE_id%num_active_cba_groups],UE_id%num_active_cba_groups );
2456

2457
            eNB->cba_last_reception[UE_id%num_active_cba_groups]+=1;
2458

2459 2460
            mac_xface->SR_indication(eNB->Mod_id,
                                     eNB->CC_id,
2461
                                     frame,
2462
                                     eNB->dlsch[UE_id][0]->rnti,subframe);
2463
          }
2464 2465 2466
        } // UNKNOWN_ACCESS
      } // ULSCH CBA not in error
  }
2467

2468
}
2469

2470 2471


2472
void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) {
2473 2474 2475 2476 2477

  int i,l;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  void *rxp[fp->nb_antennas_rx]; 
  unsigned int rxs;
2478
  eNB_proc_t *proc = &eNB->proc;
2479 2480 2481
  int subframe = proc->subframe_rx;
  int frame = proc->frame_rx;

2482

2483 2484 2485
  if (subframe==9) { 
    subframe=0;
    frame++;
Raymond Knopp's avatar
Raymond Knopp committed
2486
    frame&=1023;
2487 2488
  }
  else subframe++;
2489 2490 2491 2492

  //  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_COMMON_RX,1);
  start_meas(&eNB->phy_proc_rx);
#ifdef DEBUG_PHY_PROC
2493
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe);
2494 2495 2496 2497
#endif

  if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot)
    
2498

2499 2500
      if ((eNB->node_function == NGFI_RRU_IF4) || 
	  (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF and front-end processing
2501
	for (i=0; i<fp->nb_antennas_rx; i++)
2502
	  rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti];
2503 2504

	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
2505 2506 2507
	rxs = openair0.trx_read_func(&openair0,
				     &proc->timestamp_rx,
				     rxp,
Raymond Knopp's avatar
Raymond Knopp committed
2508
				     fp->samples_per_tti,
2509 2510 2511
				     fp->nb_antennas_rx);
	proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
	proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
Raymond Knopp's avatar
Raymond Knopp committed
2512 2513 2514 2515
	if (proc->first_rx == 0) {
	  AssertFatal(proc->subframe_rx == subframe, "Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)",proc->subframe_rx,subframe);
	  AssertFatal(proc->frame_rx == frame, "Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)",proc->frame_rx,frame);
	}
2516 2517
	else
	  proc->first_rx = 0;
2518

Raymond Knopp's avatar
Raymond Knopp committed
2519 2520
	//	printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe);

2521
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
2522 2523
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, frame );
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, subframe );
2524

2525

Raymond Knopp's avatar
Raymond Knopp committed
2526 2527
	if (rxs != fp->samples_per_tti)
	  exit_fun( "problem receiving samples" );
2528
	
Raymond Knopp's avatar
Raymond Knopp committed
2529 2530
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );

2531 2532
	// now do common RX processing for first slot in subframe
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
2533
	remove_7_5_kHz(eNB,subframe<<1);
Raymond Knopp's avatar
Raymond Knopp committed
2534 2535
	remove_7_5_kHz(eNB,1+(subframe<<1));
	for (l=0; l<fp->symbols_per_tti/2; l++) {
2536 2537 2538 2539 2540 2541 2542 2543 2544 2545
	  slot_fep_ul(fp,
		      &eNB->common_vars,
		      l,
		      subframe<<1,
		      0,
		      0
		      );
	  slot_fep_ul(fp,
		      &eNB->common_vars,
		      l,
Raymond Knopp's avatar
Raymond Knopp committed
2546
		      1+(subframe<<1),
2547 2548 2549
		      0,
		      0
		      );
Raymond Knopp's avatar
Raymond Knopp committed
2550 2551 2552
	}
    	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);

2553
	if (eNB->node_function == NGFI_RRU_IF4) {
Raymond Knopp's avatar
Raymond Knopp committed
2554
	  //send_IF4(eNB,subframe<<1);
2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571
	  //send_IF4(eNB,(subframe<<1)+1);
	}

      }
      else if (eNB->node_function == NGFI_RCC_IF4) { // => acquisition from RRU (IF4)
	// get frame/subframe information from IF4 interface

	//recv_IF4(eNB,subframe<<1);
	//recv_IF4(eNB,1+(subframe<<1));
	
      }
      else { // should not get here
	AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function);
      }
 
  
    // check if we have to detect PRACH first
2572
    if (is_prach_subframe(fp,frame,subframe)>0) {
2573 2574
      // wake up thread for PRACH RX
      if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
2575
	LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach );
2576 2577 2578 2579 2580
	exit_fun( "error locking mutex_prach" );
	return;
      }
      
      int cnt_prach = ++proc->instance_cnt_prach;
2581 2582 2583
      // set timing for prach thread
      proc->frame_prach = frame;
      proc->subframe_prach = subframe;
2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594

      pthread_mutex_unlock( &proc->mutex_prach );
      
      if (cnt_prach == 0) {
	// the thread was presumably waiting where it should and 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;
	}
      } else {
2595
	LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", frame);
2596 2597 2598 2599 2600 2601 2602
	exit_fun( "PRACH thread busy" );
	return;
      }


    }
    
2603

2604 2605 2606 2607 2608 2609 2610 2611
    
  }

  else {  // grab transport channel information from network interface

  }
}

2612
void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const uint8_t abstraction_flag,const relaying_type_t r_type)
2613
{
2614
  //RX processing for ue-specific resources (i
2615 2616 2617 2618 2619 2620 2621
  UNUSED(r_type);
  uint32_t l, ret=0,i,j,k;
  uint32_t harq_pid, harq_idx, round;
  uint8_t nPRS;
  int sync_pos;
  uint16_t rnti=0;
  uint8_t access_mode;
2622
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
2623

2624 2625
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
2626

2627
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1);
2628
  start_meas(&eNB->phy_proc_rx);
2629
#ifdef DEBUG_PHY_PROC
2630
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe);
Lionel Gauthier's avatar
Lionel Gauthier committed
2631
#endif
2632 2633


2634 2635 2636 2637
  eNB->rb_mask_ul[0]=0;
  eNB->rb_mask_ul[1]=0;
  eNB->rb_mask_ul[2]=0;
  eNB->rb_mask_ul[3]=0;
2638 2639 2640



2641
  // Check for active processes in current subframe
2642
  harq_pid = subframe2harq_pid(fp,
2643 2644 2645 2646
                               frame,subframe);

  // reset the cba flag used for collision detection
  for (i=0; i < NUM_MAX_CBA_GROUP; i++) {
2647
    eNB->cba_last_reception[i]=0;
2648 2649 2650 2651 2652
  }

  // Do PUCCH processing first

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2653
    pucch_procedures(eNB,proc,i,harq_pid,abstraction_flag);
2654
  }
2655

2656
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
2657

2658
    // check for Msg3
2659
    if (eNB->mac_enabled==1) {
2660
      if (eNB->UE_stats[i].mode == RA_RESPONSE) {
2661
	process_Msg3(eNB,proc,i,harq_pid);
2662 2663
      }
    }
2664 2665


2666 2667 2668
    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;
2669

2670 2671 2672
    if ((eNB->ulsch[i]) &&
        (eNB->ulsch[i]->rnti>0) &&
        (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) {
2673
      // UE is has ULSCH scheduling
2674
      round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
2675
 
2676
      for (int rb=0;
2677
           rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
2678
	   rb++) {
2679
	int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
2680
	eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
2681
      }
2682

2683

2684
      if (eNB->ulsch[i]->Msg3_flag == 1) {
2685
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
2686
              eNB->Mod_id,
2687 2688
              frame,
              subframe,
2689
              eNB->UE_stats[i].sector);
2690 2691
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1);
      } else {
2692

2693
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n",
2694
              eNB->Mod_id,
2695 2696 2697
              frame,
              subframe,
              i,
2698
              mode_string[eNB->UE_stats[i].mode]);
2699
      }
2700 2701


2702
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
2703

2704
      eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
2705
          nPRS)%12;
2706

2707
      if (fp->frame_type == FDD ) {
2708
        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
2709

2710 2711
        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
2712
        } else {
2713
          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
2714
        }
2715
      }
2716

2717 2718
      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",
2719
            eNB->Mod_id,harq_pid,frame,subframe,
2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
            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,
2730
            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
2731
            nPRS,
2732 2733 2734 2735
            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;
2736
      start_meas(&eNB->ulsch_demodulation_stats);
2737

2738
      if (abstraction_flag==0) {
2739
        rx_ulsch(eNB,proc,
2740
                 eNB->UE_stats[i].sector,  // this is the effective sector id
2741
                 i,
2742
                 eNB->ulsch,
2743 2744
                 0);
      }
2745

2746 2747
#ifdef PHY_ABSTRACTION
      else {
2748
        rx_ulsch_emul(eNB,proc,
2749
                      subframe,
2750
                      eNB->UE_stats[i].sector,  // this is the effective sector id
2751 2752
                      i);
      }
2753

2754
#endif
2755
      stop_meas(&eNB->ulsch_demodulation_stats);
2756

2757

2758
      start_meas(&eNB->ulsch_decoding_stats);
2759

2760
      if (abstraction_flag == 0) {
2761
        ret = ulsch_decoding(eNB,proc,
2762 2763
                             i,
                             0, // control_only_flag
2764 2765
                             eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
			     eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
2766
      }
2767

2768 2769
#ifdef PHY_ABSTRACTION
      else {
2770
        ret = ulsch_decoding_emul(eNB,proc,
2771 2772 2773
                                  i,
                                  &rnti);
      }
2774

2775
#endif
2776
      stop_meas(&eNB->ulsch_decoding_stats);
2777

2778
      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",
2779
            eNB->Mod_id,harq_pid,
2780
            frame,subframe,
2781 2782 2783 2784 2785 2786 2787 2788 2789
            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],
2790
            ret);
2791

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

2796
      eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
2797 2798
#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",
2799
            eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
2800
#endif
2801
      eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
2802

2803
      if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) {
2804
#ifdef DEBUG_PHY_PROC
2805
        //if (((frame%10) == 0) || (frame < 50))
2806
        print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
2807
#endif
2808 2809 2810
        extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
                    eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
                    &eNB->UE_stats[i],
2811
                    fp->N_RB_DL,
2812
                    &rnti, &access_mode);
2813
        eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
2814

2815
      }
2816

2817
      if (eNB->ulsch[i]->Msg3_flag == 1)
2818
	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
2819

2820
      if (ret == (1+MAX_TURBO_ITERATIONS)) {
2821

2822 2823 2824 2825
        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++;
2826

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

2829
        if (eNB->ulsch[i]->Msg3_flag == 1) {
2830
          LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
2831 2832
                eNB->Mod_id,
                eNB->CC_id,
2833
                frame,subframe, i,
2834
                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
2835
                fp->maxHARQ_Msg3Tx-1);
2836 2837

	  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",
2838
		eNB->Mod_id,harq_pid,
2839
		frame,subframe,
2840 2841 2842 2843 2844 2845 2846 2847 2848
		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],
2849 2850
		ret);

2851
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round ==
2852
              fp->maxHARQ_Msg3Tx) {
2853
            LOG_D(PHY,"[eNB %d][RAPROC] maxHARQ_Msg3Tx reached, abandoning RA procedure for UE %d\n",
2854
                  eNB->Mod_id, i);
2855
            eNB->UE_stats[i].mode = PRACH;
2856 2857 2858
	    if (eNB->mac_enabled==1) {
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
2859
					frame,
2860
					eNB->UE_stats[i].crnti);
2861
	    }
2862
            mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
2863

2864 2865
            eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
            //eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 0;
2866

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

2871
            get_Msg3_alloc_ret(fp,
2872
                               subframe,
2873
                               frame,
2874 2875
                               &eNB->ulsch[i]->Msg3_frame,
                               &eNB->ulsch[i]->Msg3_subframe);
2876 2877 2878
          }
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
        } // This is Msg3 error
2879

2880 2881
        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",
2882
                eNB->Mod_id,harq_pid,
2883
                frame,subframe, i,
2884 2885 2886 2887
                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]);
2888 2889 2890 2891 2892 2893 2894

#if defined(MESSAGE_CHART_GENERATOR_PHY)
          MSC_LOG_RX_DISCARDED_MESSAGE(
            MSC_PHY_ENB,MSC_PHY_UE,
            NULL,0,
            "%05u:%02u ULSCH received rnti %x harq id %u round %d",
            frame,subframe,
2895 2896
            eNB->ulsch[i]->rnti,harq_pid,
            eNB->ulsch[i]->harq_processes[harq_pid]->round-1
2897
            );
2898
#endif
2899

2900
          if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) {
2901
            LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
2902
                  eNB->Mod_id,harq_pid,
2903
                  frame,subframe, i,
2904
                  eNB->ulsch[i]->Mlimit);
2905

2906 2907 2908 2909
            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++;
2910 2911

	    // indicate error to MAC
2912 2913
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
2914
			      frame,subframe,
2915
			      eNB->ulsch[i]->rnti,
2916 2917 2918
			      NULL,
			      0,
			      harq_pid,
2919
			      &eNB->ulsch[i]->Msg3_flag);
2920 2921 2922 2923
          }
        }
      }  // ulsch in error
      else {
2924
        if (eNB->ulsch[i]->Msg3_flag == 1) {
2925
	  LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
2926
		eNB->Mod_id,harq_pid,
2927 2928
		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",
2929
		eNB->Mod_id,harq_pid,
2930
		frame,subframe,
2931 2932 2933 2934 2935 2936 2937 2938 2939
		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],
2940 2941 2942 2943 2944 2945 2946 2947
		ret);
	}
#if defined(MESSAGE_CHART_GENERATOR_PHY)
        MSC_LOG_RX_MESSAGE(
          MSC_PHY_ENB,MSC_PHY_UE,
          NULL,0,
          "%05u:%02u ULSCH received rnti %x harq id %u",
          frame,subframe,
2948
          eNB->ulsch[i]->rnti,harq_pid
2949
          );
2950
#endif
2951
        for (j=0; j<fp->nb_antennas_rx; j++)
2952
          //this is the RSSI per RB
2953
          eNB->UE_stats[i].UL_rssi[j] =
2954
	    
2955 2956
            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
                     (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
2957
                     fp->ofdm_symbol_size) -
2958 2959
            eNB->rx_total_gain_dB -
            hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
2960
            get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
2961
	    
2962 2963 2964 2965
        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;
2966

2967
        if (eNB->ulsch[i]->Msg3_flag == 1) {
2968
	  if (eNB->mac_enabled==1) {
2969

2970
	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
2971
		  eNB->Mod_id,
2972 2973
		  frame,harq_pid,i);
	    
2974 2975
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
2976
			      frame,subframe,
2977 2978 2979
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
2980
			      harq_pid,
2981
			      &eNB->ulsch[i]->Msg3_flag);
2982 2983
	    
	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
2984 2985
	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
	      eNB->UE_stats[i].mode = PRACH;
2986 2987
	      mac_xface->cancel_ra_proc(eNB->Mod_id,
					eNB->CC_id,
2988
					frame,
2989 2990 2991
					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;
2992 2993 2994
	    } // Msg3_flag == 0
	    
	  } // mac_enabled==1
2995

2996 2997
          eNB->UE_stats[i].mode = PUSCH;
          eNB->ulsch[i]->Msg3_flag = 0;
2998

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

3001
          for (k=0; k<8; k++) { //harq_processes
3002 3003 3004 3005
            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;
3006
            }
3007

3008 3009 3010
            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;
3011

3012 3013 3014 3015 3016
            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;
3017
            }
3018 3019
          }

3020 3021 3022
          eNB->UE_stats[i].dlsch_sliding_cnt=0;
          eNB->UE_stats[i].dlsch_NAK_round0=0;
          eNB->UE_stats[i].dlsch_mcs_offset=0;
3023 3024 3025
        } // Msg3_flag==1
	else {  // Msg3_flag == 0

3026
#ifdef DEBUG_PHY_PROC
3027 3028
#ifdef DEBUG_ULSCH
          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
3029
                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
3030

3031 3032
          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]);
3033 3034 3035

          LOG_T(PHY,"\n");
#endif
3036
#endif
3037

3038
	  if (eNB->mac_enabled==1) {
3039

3040 3041
	    mac_xface->rx_sdu(eNB->Mod_id,
			      eNB->CC_id,
3042
			      frame,subframe,
3043 3044 3045
			      eNB->ulsch[i]->rnti,
			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
3046 3047
			      harq_pid,
			      NULL);
3048

3049
#ifdef LOCALIZATION
3050 3051
	    start_meas(&eNB->localization_stats);
	    aggregate_eNB_UE_localization_stats(eNB,
3052 3053 3054
						i,
						frame,
						subframe,
3055 3056
						get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
	    stop_meas(&eNB->localization_stats);
3057
#endif
3058 3059 3060
	    
	  } // mac_enabled==1
        } // Msg3_flag == 0
3061

3062 3063
        // estimate timing advance for MAC
        if (abstraction_flag == 0) {
3064
          sync_pos = lte_est_timing_advance_pusch(eNB,i);
3065
          eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
3066
        }
3067

3068 3069
#ifdef DEBUG_PHY_PROC
        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
3070
              eNB->Mod_id,
3071 3072
              frame, subframe,
              i,
3073
              eNB->UE_stats[i].timing_advance_update);
3074
#endif
3075 3076


3077 3078 3079
      }  // ulsch not in error

      // process HARQ feedback
3080
#ifdef DEBUG_PHY_PROC
3081
      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
3082
            eNB->dlsch[i][0]->rnti,
3083 3084
            frame,subframe,
            i);
3085
#endif
3086
      process_HARQ_feedback(i,
3087
                            eNB,proc,
3088 3089 3090 3091 3092 3093 3094
                            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",
3095
            eNB->Mod_id,frame,subframe,
3096
            eNB->UE_stats[i].sector,
3097 3098 3099
            harq_pid,
            i,
            ret,
3100 3101 3102 3103 3104
            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]);
3105 3106 3107 3108
#endif
      
      // dump stats to VCD
      if (i==0) {
3109 3110 3111
	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]);
3112
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
3113 3114
	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
3115
      }
3116
    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
3117

3118

3119
    // update ULSCH statistics for tracing
3120
    if ((frame % 100 == 0) && (subframe == 4)) {
3121
      for (harq_idx=0; harq_idx<8; harq_idx++) {
3122 3123 3124 3125 3126 3127 3128 3129
        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]);
3130
          } else {
3131
            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
3132 3133
          }

3134 3135 3136 3137
          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];
3138
        }
3139 3140
      }
    }
3141

Florian Kaltenberger's avatar
Florian Kaltenberger committed
3142
    if ((frame % 100 == 0) && (subframe==4)) {
3143 3144
      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
          eNB->UE_stats[i].total_TBS_last);
3145

3146
      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
3147
    }
3148

3149
    // CBA (non-LTE)
3150
    cba_procedures(eNB,proc,i,harq_pid,abstraction_flag);
3151 3152
  } // loop i=0 ... NUMBER_OF_UE_MAX-1

3153
  if (abstraction_flag == 0) {
3154
    lte_eNB_I0_measurements(eNB,
3155 3156
			    subframe,
			    0,
3157 3158
			    eNB->first_run_I0_measurements);
    eNB->first_run_I0_measurements = 0;
3159
  }
3160

3161
#ifdef PHY_ABSTRACTION
3162
    else {
3163
      lte_eNB_I0_measurements_emul(eNB,
3164
                                   0);
3165
    }
3166

3167
#endif
3168 3169


3170
    //}
3171 3172

#ifdef EMOS
3173
  phy_procedures_emos_eNB_RX(subframe,eNB);
3174 3175
#endif

3176
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,0);
3177
  stop_meas(&eNB->phy_proc_rx);
3178

3179 3180 3181 3182
}

#undef DEBUG_PHY_PROC

3183 3184 3185 3186
#ifdef Rel10
int phy_procedures_RN_eNB_TX(unsigned char last_slot, unsigned char next_slot, relaying_type_t r_type)
{

3187
  int do_proc=0;// do nothing
3188 3189

  switch(r_type) {
3190
  case no_relay:
3191
    do_proc= no_relay; // perform the normal eNB operation
3192
    break;
3193

3194
  case multicast_relay:
3195
    if (((next_slot >>1) < 6) || ((next_slot >>1) > 8))
3196
      do_proc = 0; // do nothing
3197 3198 3199
    else // SF#6, SF#7 and SF#8
      do_proc = multicast_relay; // do PHY procedures eNB TX

3200
    break;
3201

3202 3203
  default: // should'not be here
    LOG_W(PHY,"Not supported relay type %d, do nothing\n", r_type);
3204
    do_proc=0;
3205 3206
    break;
  }
3207

3208 3209
  return do_proc;
}
3210
#endif
3211
/*
3212 3213
void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **eNB,uint8_t abstraction_flag,
                            relaying_type_t r_type, PHY_VARS_RN *rn)
3214
{
3215
#if defined(ENABLE_ITTI)
3216 3217 3218 3219 3220
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  unsigned int  Mod_id;
  int           result;
3221
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
3222

Raymond Knopp's avatar
 
Raymond Knopp committed
3223 3224 3225

  int CC_id=0;

3226

3227
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_ENB, eNB[0]->proc[subframe].frame_tx);
3228
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,1);
3229
  start_meas(&eNB[0]->phy_proc);
Lionel Gauthier's avatar
Lionel Gauthier committed
3230

3231
#if defined(ENABLE_ITTI)
3232

3233
  do {
3234 3235
    // Checks if a message has been sent to PHY sub-task
    itti_poll_msg (TASK_PHY_ENB, &msg_p);
3236

3237 3238 3239 3240
    if (msg_p != NULL) {
      msg_name = ITTI_MSG_NAME (msg_p);
      instance = ITTI_MSG_INSTANCE (msg_p);
      Mod_id = instance;
3241

3242
      switch (ITTI_MSG_ID(msg_p)) {
3243

3244
        // Messages from eNB app
Raymond Knopp's avatar
 
Raymond Knopp committed
3245
      case PHY_CONFIGURATION_REQ:
3246
        LOG_I(PHY, "[eNB %d] Received %s\n", instance, msg_name);
3247
        // TODO
3248

3249
        break;
3250

Raymond Knopp's avatar
 
Raymond Knopp committed
3251
      default:
3252 3253
        LOG_E(PHY, "[ENB %d] Received unexpected message %s\n", Mod_id, msg_name);
        break;
Lionel Gauthier's avatar
Lionel Gauthier committed
3254
      }
3255 3256 3257 3258

      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
      AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    }
3259
  } while(msg_p != NULL);
3260

3261 3262
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
3263

3264
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
3265 3266 3267
    if ((((eNB[CC_id]->frame_parms.frame_type == TDD)&&
          (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_tx)==SF_DL))||
         (eNB[CC_id]->frame_parms.frame_type == FDD))) {
3268 3269
#ifdef Rel10

3270
      if (phy_procedures_RN_eNB_TX(eNB[CC_id]->proc[0].subframe_rx, eNB[CC_id]->proc[0].subframe_tx, r_type) != 0 )
3271
#endif
3272
        phy_procedures_eNB_TX(subframe,eNB[CC_id],abstraction_flag,r_type,rn);
Raymond Knopp's avatar
 
Raymond Knopp committed
3273
    }
3274

3275 3276 3277
    if ((((eNB[CC_id]->frame_parms.frame_type == TDD )&&
          (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_rx)==SF_UL)) ||
         (eNB[CC_id]->frame_parms.frame_type == FDD))) {
3278
      phy_procedures_eNB_RX(subframe,eNB[CC_id],abstraction_flag,r_type);
Raymond Knopp's avatar
 
Raymond Knopp committed
3279
    }
3280

3281
    if (subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_tx)==SF_S) {
3282 3283
#ifdef Rel10

Raymond Knopp's avatar
 
Raymond Knopp committed
3284
      if (phy_procedures_RN_eNB_TX(subframe, subframe, r_type) != 0 )
3285
#endif
3286
        phy_procedures_eNB_TX(subframe,eNB[CC_id],abstraction_flag,r_type,rn);
Raymond Knopp's avatar
 
Raymond Knopp committed
3287
    }
3288

3289
    if ((subframe_select(&eNB[CC_id]->frame_parms,eNB[CC_id]->proc[0].subframe_rx)==SF_S)) {
3290
      phy_procedures_eNB_S_RX(subframe,eNB[CC_id],abstraction_flag,r_type);
Raymond Knopp's avatar
 
Raymond Knopp committed
3291
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
3292

3293 3294
    eNB[CC_id]->proc[0].frame_tx++;
    eNB[CC_id]->proc[0].frame_rx++;
3295

3296 3297
    if (eNB[CC_id]->proc[0].frame_tx>=MAX_FRAME_NUMBER) // defined in impl_defs_top.h
      eNB[CC_id]->proc[0].frame_tx-=MAX_FRAME_NUMBER;
3298

3299 3300
    if (eNB[CC_id]->proc[0].frame_rx>=MAX_FRAME_NUMBER)
      eNB[CC_id]->proc[0].frame_rx-=MAX_FRAME_NUMBER;
Raymond Knopp's avatar
 
Raymond Knopp committed
3301
  }
3302

3303
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,0);
3304
  stop_meas(&eNB[0]->phy_proc);
3305
}
3306
*/