phy_procedures_lte_eNb.c 139 KB
Newer Older
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 60
#include "T.h"

61
#include "assertions.h"
gauthier's avatar
gauthier committed
62
#include "msc.h"
63

64
#if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
65
#   include "intertask_interface.h"
66
#   if ENABLE_RAL
gauthier's avatar
gauthier committed
67 68
#     include "timer.h"
#   endif
69 70
#endif

71 72 73 74 75 76 77 78 79
//#define DIAG_PHY

#define NS_PER_SLOT 500000

#define PUCCH 1

extern int exit_openair;


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

85
extern uint16_t hundred_times_log10_NPRB[100];
86

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

//DCI_ALLOC_t dci_alloc[8];

#ifdef EMOS
fifo_dump_emos_eNB emos_dump_eNB;
#endif

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

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

106 107
uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id,uint8_t sched_subframe)
{
108

gauthier's avatar
gauthier committed
109 110
  const int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx;
  const int frame = phy_vars_eNB->proc[sched_subframe].frame_rx;
111

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

116
  if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 4) {        // 5 ms SR period
117 118
    if ((subframe%5) == phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex)
      return(1);
119
  } else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 14) { // 10 ms SR period
120 121
    if (subframe==(phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-5))
      return(1);
122
  } else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 34) { // 20 ms SR period
123
    if ((10*(frame&1)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-15))
124
      return(1);
125
  } else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 74) { // 40 ms SR period
126
    if ((10*(frame&3)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-35))
127
      return(1);
128
  } else if (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex <= 154) { // 80 ms SR period
129
    if ((10*(frame&7)+subframe) == (phy_vars_eNB->scheduling_request_config[UE_id].sr_ConfigIndex-75))
130
      return(1);
131 132 133 134
  }

  return(0);
}
135 136 137

int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB)
{
138
  uint8_t i;
139

140
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
141 142 143 144
  LOG_I(PHY,"[eNB %d/%d] Adding UE with rnti %x\n",
        phy_vars_eNB->Mod_id,
        phy_vars_eNB->CC_id,
        (uint16_t)rnti);
145
#endif
146 147

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

	phy_vars_eNB->eNB_UE_stats[i].Po_PUCCH1_below = 0;
	phy_vars_eNB->eNB_UE_stats[i].Po_PUCCH1_above = (int32_t)pow(10.0,.1*(phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH+phy_vars_eNB->rx_total_gain_eNB_dB));
	phy_vars_eNB->eNB_UE_stats[i].Po_PUCCH        = (int32_t)pow(10.0,.1*(phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH+phy_vars_eNB->rx_total_gain_eNB_dB));
163
	LOG_D(PHY,"Initializing Po_PUCCH: p0_NominalPUCCH %d, gain %d => %d\n",
knopp's avatar
knopp committed
164 165 166 167
	      phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH,
	      phy_vars_eNB->rx_total_gain_eNB_dB,
	      phy_vars_eNB->eNB_UE_stats[i].Po_PUCCH);
  
168
        return(i);
169
      }
170
    }
171 172 173 174
  }
  return(-1);
}

175
int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) {
176
  uint8_t i;
177 178 179 180 181 182 183 184 185 186 187 188 189
  int j,CC_id;
  PHY_VARS_eNB *phy_vars_eNB;

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
    phy_vars_eNB = PHY_vars_eNB_g[Mod_idP][CC_id];
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
      if ((phy_vars_eNB->dlsch_eNB[i]==NULL) || (phy_vars_eNB->ulsch_eNB[i]==NULL)) {
	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 {
	if (phy_vars_eNB->eNB_UE_stats[i].crnti==rntiP) {
	  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Removed ue %"PRIx16" ", rntiP);
190
#ifdef DEBUG_PHY_PROC
191 192 193 194 195 196 197 198 199 200 201
	  LOG_I(PHY,"eNB %d removing UE %d with rnti %x\n",phy_vars_eNB->Mod_id,i,rnti);
#endif
	  //msg("[PHY] UE_id %d\n",i);
	  clean_eNb_dlsch(phy_vars_eNB->dlsch_eNB[i][0]);
	  clean_eNb_ulsch(phy_vars_eNB->ulsch_eNB[i]);
	  //phy_vars_eNB->eNB_UE_stats[i].crnti = 0;
	  memset(&phy_vars_eNB->eNB_UE_stats[i],0,sizeof(LTE_eNB_UE_stats));
	  //  mac_exit_wrapper("Removing UE");
	  
	  return(i);
	}
202
      }
203
    }
204
  }
205
  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (not found)", rntiP);
206 207 208
  return(-1);
}

209 210
int8_t find_next_ue_index(PHY_VARS_eNB *phy_vars_eNB)
{
211
  uint8_t i;
212

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

223 224 225
  return(-1);
}

gauthier's avatar
gauthier committed
226
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)
227 228 229 230
{
  LTE_eNB_DLSCH_t *DLSCH_ptr;
  LTE_eNB_ULSCH_t *ULSCH_ptr;
  uint8_t ulsch_subframe,ulsch_frame;
231
  int i;
232
  int8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]);
233 234

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

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

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

246 247 248 249 250
    if (DLSCH_ptr->harq_processes[i]->status == ACTIVE) {
      *harq_pid = i;
      *round = DLSCH_ptr->harq_processes[i]->round;
    } else if (DLSCH_ptr->harq_processes[i]->status == SCH_IDLE) {
      *harq_pid = i;
251
      *round = 0;
252 253 254
    } else {
      printf("%s:%d: bad state for harq process - PLEASE REPORT!!\n", __FILE__, __LINE__);
      abort();
255
    }
256
  } else { // This is a UL request
257

258 259 260
    ULSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->ulsch_eNB[(uint32_t)UE_id];
    ulsch_subframe = pdcch_alloc2ul_subframe(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,subframe);
    ulsch_frame    = pdcch_alloc2ul_frame(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,frame,subframe);
261
    // Note this is for TDD configuration 3,4,5 only
262
    *harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,
263 264
                                  ulsch_frame,
                                  ulsch_subframe);
265
    *round    = ULSCH_ptr->harq_processes[*harq_pid]->round;
266
    LOG_T(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d Checking HARQ, round %d\n",Mod_id,*harq_pid,frame,subframe,*round);
267
  }
268

269 270 271
  return(0);
}

knopp's avatar
knopp committed
272
int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
273
{
274 275
  //return PHY_vars_eNB_g[module_idP][CC_id]->PHY_measurements_eNB[0].n0_power_tot_dBm;
  return PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
276 277
}

knopp's avatar
knopp committed
278 279 280 281 282 283
int16_t get_target_pucch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
{
  //return PHY_vars_eNB_g[module_idP][CC_id]->PHY_measurements_eNB[0].n0_power_tot_dBm;
  return PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
}

284
#ifdef EMOS
285 286
void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *phy_vars_eNB)
{
287 288 289 290

}
#endif

291

292

293 294 295
void phy_procedures_eNB_S_RX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type)
{
  UNUSED(r_type);
296

297
  int subframe = phy_vars_eNB->proc[sched_subframe].subframe_rx;
298

299
#ifdef DEBUG_PHY_PROC
300
  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_S_RX(%d)\n", phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_rx, subframe);
301
#endif
302

303

304 305
  if (abstraction_flag == 0) {
    lte_eNB_I0_measurements(phy_vars_eNB,
306
			    subframe,
307 308
                            0,
                            phy_vars_eNB->first_run_I0_measurements);
309
  }
310

311
#ifdef PHY_ABSTRACTION
312 313
  else {
    lte_eNB_I0_measurements_emul(phy_vars_eNB,
314
                                 0);
315
  }
316

317 318
#endif

319

320 321
}

322 323


324
#ifdef EMOS
325 326 327
void phy_procedures_emos_eNB_RX(unsigned char subframe,PHY_VARS_eNB *phy_vars_eNB)
{

328 329 330 331
  uint8_t aa;
  uint16_t last_subframe_emos;
  uint16_t pilot_pos1 = 3 - phy_vars_eNB->lte_frame_parms.Ncp, pilot_pos2 = 10 - 2*phy_vars_eNB->lte_frame_parms.Ncp;
  uint32_t bytes;
332 333 334

  last_subframe_emos=0;

335

336

337

338
#ifdef EMOS_CHANNEL
339

340
  //if (last_slot%2==1) // this is for all UL subframes
341
  if (subframe==3)
342
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_rx; aa++) {
343 344 345 346 347 348
      memcpy(&emos_dump_eNB.channel[aa][last_subframe_emos*2*phy_vars_eNB->lte_frame_parms.N_RB_UL*12],
             &phy_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][aa][phy_vars_eNB->lte_frame_parms.N_RB_UL*12*pilot_pos1],
             phy_vars_eNB->lte_frame_parms.N_RB_UL*12*sizeof(int));
      memcpy(&emos_dump_eNB.channel[aa][(last_subframe_emos*2+1)*phy_vars_eNB->lte_frame_parms.N_RB_UL*12],
             &phy_vars_eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][aa][phy_vars_eNB->lte_frame_parms.N_RB_UL*12*pilot_pos2],
             phy_vars_eNB->lte_frame_parms.N_RB_UL*12*sizeof(int));
349
    }
350

351 352
#endif

353
  if (subframe==4) {
354
    emos_dump_eNB.timestamp = rt_get_time_ns();
jiangx's avatar
jiangx committed
355
    emos_dump_eNB.frame_tx = phy_vars_eNB->proc[subframe].frame_rx;
356 357 358 359 360 361 362 363
    emos_dump_eNB.rx_total_gain_dB = phy_vars_eNB->rx_total_gain_eNB_dB;
    emos_dump_eNB.mimo_mode = phy_vars_eNB->transmission_mode[0];
    memcpy(&emos_dump_eNB.PHY_measurements_eNB,
           &phy_vars_eNB->PHY_measurements_eNB[0],
           sizeof(PHY_MEASUREMENTS_eNB));
    memcpy(&emos_dump_eNB.eNB_UE_stats[0],&phy_vars_eNB->eNB_UE_stats[0],NUMBER_OF_UE_MAX*sizeof(LTE_eNB_UE_stats));

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

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


#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
#define AMP_OVER_2 (AMP>>1)
382 383
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)};
384

gauthier's avatar
gauthier committed
385 386

#if defined(ENABLE_ITTI)
387
#   if ENABLE_RAL
gauthier's avatar
gauthier committed
388 389
extern PHY_MEASUREMENTS PHY_measurements;

390 391
void phy_eNB_lte_measurement_thresholds_test_and_report(instance_t instanceP, ral_threshold_phy_t* threshold_phy_pP, uint16_t valP)
{
392
  MessageDef *message_p = NULL;
393

394
  if (
395 396 397 398 399 400
    (
      ((threshold_phy_pP->threshold.threshold_val <  valP) && (threshold_phy_pP->threshold.threshold_xdir == RAL_ABOVE_THRESHOLD)) ||
      ((threshold_phy_pP->threshold.threshold_val >  valP) && (threshold_phy_pP->threshold.threshold_xdir == RAL_BELOW_THRESHOLD))
    )  ||
    (threshold_phy_pP->threshold.threshold_xdir == RAL_NO_THRESHOLD)
  ) {
401 402 403 404
    message_p = itti_alloc_new_message(TASK_PHY_ENB , PHY_MEAS_REPORT_IND);
    memset(&PHY_MEAS_REPORT_IND(message_p), 0, sizeof(PHY_MEAS_REPORT_IND(message_p)));

    memcpy(&PHY_MEAS_REPORT_IND (message_p).threshold,
405 406
           &threshold_phy_pP->threshold,
           sizeof(PHY_MEAS_REPORT_IND (message_p).threshold));
407 408

    memcpy(&PHY_MEAS_REPORT_IND (message_p).link_param,
409 410 411
           &threshold_phy_pP->link_param,
           sizeof(PHY_MEAS_REPORT_IND (message_p).link_param));
    \
412 413 414 415 416

    switch (threshold_phy_pP->link_param.choice) {
    case RAL_LINK_PARAM_CHOICE_LINK_PARAM_VAL:
      PHY_MEAS_REPORT_IND (message_p).link_param._union.link_param_val = valP;
      break;
417

418 419 420 421
    case RAL_LINK_PARAM_CHOICE_QOS_PARAM_VAL:
      //PHY_MEAS_REPORT_IND (message_p).link_param._union.qos_param_val.
      AssertFatal (1 == 0, "TO DO RAL_LINK_PARAM_CHOICE_QOS_PARAM_VAL\n");
      break;
422
    }
423

424 425
    itti_send_msg_to_task(TASK_RRC_ENB, instanceP, message_p);
  }
gauthier's avatar
gauthier committed
426 427
}

428 429
void phy_eNB_lte_check_measurement_thresholds(instance_t instanceP, ral_threshold_phy_t* threshold_phy_pP)
{
430 431 432 433 434 435 436 437 438 439 440
  unsigned int  mod_id;

  mod_id = instanceP;

  switch (threshold_phy_pP->link_param.link_param_type.choice) {

  case RAL_LINK_PARAM_TYPE_CHOICE_GEN:
    switch (threshold_phy_pP->link_param.link_param_type._union.link_param_gen) {
    case RAL_LINK_PARAM_GEN_DATA_RATE:
      phy_eNB_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0);
      break;
441

442 443 444
    case RAL_LINK_PARAM_GEN_SIGNAL_STRENGTH:
      phy_eNB_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0);
      break;
445

446 447 448
    case RAL_LINK_PARAM_GEN_SINR:
      phy_eNB_lte_measurement_thresholds_test_and_report(instanceP, threshold_phy_pP, 0);
      break;
449

450 451
    case RAL_LINK_PARAM_GEN_THROUGHPUT:
      break;
452

453 454
    case RAL_LINK_PARAM_GEN_PACKET_ERROR_RATE:
      break;
455 456 457

    default:
      ;
gauthier's avatar
gauthier committed
458
    }
459

460 461 462 463 464 465
    break;

  case RAL_LINK_PARAM_TYPE_CHOICE_LTE:
    switch (threshold_phy_pP->link_param.link_param_type._union.link_param_gen) {
    case RAL_LINK_PARAM_LTE_UE_RSRP:
      break;
466

467 468
    case RAL_LINK_PARAM_LTE_UE_RSRQ:
      break;
469

470 471
    case RAL_LINK_PARAM_LTE_UE_CQI:
      break;
472

473 474
    case RAL_LINK_PARAM_LTE_AVAILABLE_BW:
      break;
475

476 477
    case RAL_LINK_PARAM_LTE_PACKET_DELAY:
      break;
478

479 480
    case RAL_LINK_PARAM_LTE_PACKET_LOSS_RATE:
      break;
481

482 483
    case RAL_LINK_PARAM_LTE_L2_BUFFER_STATUS:
      break;
484

485 486
    case RAL_LINK_PARAM_LTE_MOBILE_NODE_CAPABILITIES:
      break;
487

488 489
    case RAL_LINK_PARAM_LTE_EMBMS_CAPABILITY:
      break;
490

491 492
    case RAL_LINK_PARAM_LTE_JUMBO_FEASIBILITY:
      break;
493

494 495
    case RAL_LINK_PARAM_LTE_JUMBO_SETUP_STATUS:
      break;
496

497 498
    case RAL_LINK_PARAM_LTE_NUM_ACTIVE_EMBMS_RECEIVERS_PER_FLOW:
      break;
499 500 501

    default:
      ;
502
    }
503

504 505
    break;

506 507
  default:
    ;
508
  }
gauthier's avatar
gauthier committed
509 510 511 512
}
#   endif
#endif

513

Cedric Roux's avatar
Cedric Roux committed
514
unsigned int taus(void);
Dominique Nussbaum's avatar
Dominique Nussbaum committed
515
DCI_PDU DCI_pdu_tmp;
516

517
void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,
518 519
                           relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn)
{
520
  UNUSED(phy_vars_rn);
521 522
  uint8_t *pbch_pdu=&phy_vars_eNB->pbch_pdu[0];
  uint16_t input_buffer_length, re_allocated=0;
523
  uint32_t i,aa;
524
  uint8_t harq_pid;
525
  DCI_PDU *DCI_pdu;
526
  uint8_t *DLSCH_pdu=NULL;
Dominique Nussbaum's avatar
Dominique Nussbaum committed
527
  //DCI_PDU DCI_pdu_tmp;
528 529 530 531 532
  uint8_t DLSCH_pdu_tmp[768*8];
  int8_t UE_id;
  uint8_t num_pdcch_symbols=0;
  uint8_t ul_subframe;
  uint32_t ul_frame;
533
#ifdef Rel10
534 535
  MCH_PDU *mch_pduP;
  MCH_PDU  mch_pdu;
536
  //  uint8_t sync_area=255;
537 538 539 540
#endif
#if defined(SMBV) && !defined(EXMIMO)
  // counts number of allocations in subframe
  // there is at least one allocation for PDCCH
541
  uint8_t smbv_alloc_cnt = 1;
542
#endif
543
  int frame = phy_vars_eNB->proc[sched_subframe].frame_tx;
544
  int subframe = phy_vars_eNB->proc[sched_subframe].subframe_tx;
545

gauthier's avatar
gauthier committed
546
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,1);
547
  start_meas(&phy_vars_eNB->phy_proc_tx);
548

549
  T(T_ENB_PHY_DL_TICK, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe));
550

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

554
    if (phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) {
555
      LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n",
556 557
            phy_vars_eNB->Mod_id,phy_vars_eNB->CC_id,frame,subframe, i, phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors);
      phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0;
558 559 560 561 562 563
      mac_xface->UL_failure_indication(phy_vars_eNB->Mod_id,
				       phy_vars_eNB->CC_id,
				       frame,
				       phy_vars_eNB->eNB_UE_stats[i].crnti,
				       subframe);
				       
564
    }
565
	
566

567 568 569
  }


570
  // Get scheduling info for next subframe
571 572 573 574 575
  if (phy_vars_eNB->mac_enabled==1) {
    if (phy_vars_eNB->CC_id == 0) {
      mac_xface->eNB_dlsch_ulsch_scheduler(phy_vars_eNB->Mod_id,0,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe);//,1);
    }
  }
576

577
  if (abstraction_flag==0) {
578
    // clear the transmit data array for the current subframe
579 580
    for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx_eNB; aa++) {

581
      memset(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][subframe*phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti)],
582
             0,phy_vars_eNB->lte_frame_parms.ofdm_symbol_size*(phy_vars_eNB->lte_frame_parms.symbols_per_tti)*sizeof(int32_t));
583 584
    }
  }
585 586


587
  if (is_pmch_subframe(phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,&phy_vars_eNB->lte_frame_parms)) {
588

589
    if (abstraction_flag==0) {
590 591
      // This is DL-Cell spec pilots in Control region
      generate_pilots_slot(phy_vars_eNB,
592 593 594
                           phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
                           AMP,
                           subframe<<1,1);
595
    }
596

597
#ifdef Rel10
598
    // if mcch is active, send regardless of the node type: eNB or RN
599
    // when mcch is active, MAC sched does not allow MCCH and MTCH multiplexing
600
    mch_pduP = mac_xface->get_mch_sdu(phy_vars_eNB->Mod_id,
601 602 603 604 605
                                      phy_vars_eNB->CC_id,
                                      phy_vars_eNB->proc[sched_subframe].frame_tx,
                                      subframe);

    switch (r_type) {
606
    case no_relay:
607
      if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0
608
        LOG_I(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n",
609 610
              phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,mch_pduP->mcs,
              phy_vars_eNB->dlsch_eNB_MCH->harq_processes[0]->TBS>>3);
611
      else {
612
        LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n",
613 614 615
              phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,mch_pduP->sync_area,
              (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment");
        mch_pduP = NULL;
616
      }
617

618
      break;
619

620
    case multicast_relay:
621
      if ((mch_pduP->Pdu_size > 0) && ((mch_pduP->mcch_active == 1) || mch_pduP->msi_active==1)) {
622
        LOG_I(PHY,"[RN %"PRIu8"] Frame %d subframe %d: Got the MCH PDU for MBSFN  sync area %"PRIu8" (MCS %"PRIu8", TBS %"PRIu16")\n",
623 624 625 626 627 628 629 630 631
              phy_vars_rn->Mod_id,phy_vars_rn->frame, subframe,
              mch_pduP->sync_area,mch_pduP->mcs,mch_pduP->Pdu_size);
      } else if (phy_vars_rn->mch_avtive[subframe%5] == 1) { // SF2 -> SF7, SF3 -> SF8
        mch_pduP= &mch_pdu;
        memcpy(&mch_pduP->payload, // could be a simple copy
               phy_vars_rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->b,
               phy_vars_rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3);
        mch_pduP->Pdu_size = (uint16_t) (phy_vars_rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->TBS>>3);
        mch_pduP->mcs = phy_vars_rn->dlsch_rn_MCH[subframe%5]->harq_processes[0]->mcs;
632
        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",
633 634
              phy_vars_rn->Mod_id,phy_vars_rn->frame, subframe,subframe%5,
              phy_vars_rn->sync_area[subframe%5],mch_pduP->mcs,mch_pduP->Pdu_size);
635
      } else {
636
        mch_pduP=NULL;
637
      }
638

639 640
      phy_vars_rn->mch_avtive[subframe]=0;
      break;
641

642
    default:
643
      LOG_W(PHY,"[eNB %"PRIu8"] Frame %d subframe %d: unknown relaying type %d \n",
644
            phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,r_type);
645 646
      mch_pduP=NULL;
      break;
647 648 649
    }// switch

    if (mch_pduP) {
650 651
      fill_eNB_dlsch_MCH(phy_vars_eNB,mch_pduP->mcs,1,0, abstraction_flag);
      // Generate PMCH
652
      generate_mch(phy_vars_eNB,sched_subframe,(uint8_t*)mch_pduP->payload,abstraction_flag);
653
#ifdef DEBUG_PHY
654 655

      for (i=0; i<mch_pduP->Pdu_size; i++)
656
        msg("%2"PRIx8".",(uint8_t)mch_pduP->payload[i]);
657

658
      msg("\n");
659
#endif
660 661
    } else {
      LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe);
662
    }
663

664 665
#endif
  }
666

667
  else {
668
    // this is not a pmch subframe
669 670

    if (abstraction_flag==0) {
gauthier's avatar
gauthier committed
671
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
672
      generate_pilots_slot(phy_vars_eNB,
673 674 675
                           phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
                           AMP,
                           subframe<<1,0);
676 677 678 679 680 681
      if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_DL)
	generate_pilots_slot(phy_vars_eNB,
			     phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
			     AMP,
			     (subframe<<1)+1,0);

gauthier's avatar
gauthier committed
682
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0);
683

684 685
      // First half of PSS/SSS (FDD)
      if (subframe == 0) {
686 687
        if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) {
          generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
688
                       AMP,
689
                       &phy_vars_eNB->lte_frame_parms,
690
                       (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5,
691 692
                       0);
          generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
693
                       AMP,
694
                       &phy_vars_eNB->lte_frame_parms,
695
                       (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 5 : 4,
696 697 698 699
                       0);

        }
      }
700
    }
701
  }
702

703
  if (subframe == 0) {
704
    // generate PBCH (Physical Broadcast CHannel) info
705
    if ((phy_vars_eNB->proc[sched_subframe].frame_tx&3) == 0) {
706
      pbch_pdu[2] = 0;
707

708
      // FIXME setting pbch_pdu[2] to zero makes the switch statement easier: remove all the or-operators
709 710
      switch (phy_vars_eNB->lte_frame_parms.N_RB_DL) {
      case 6:
711
        pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (0<<5);
712 713
        break;

714
      case 15:
715
        pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (1<<5);
716 717
        break;

718
      case 25:
719
        pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
720 721
        break;

722
      case 50:
723
        pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (3<<5);
724 725
        break;

726
      case 75:
727
        pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (4<<5);
728 729
        break;

730
      case 100:
731
        pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (5<<5);
732 733
        break;

734
      default:
735 736
        // FIXME if we get here, this should be flagged as an error, right?
        pbch_pdu[2] = (pbch_pdu[2]&0x1f) | (2<<5);
737
        break;
738
      }
739

740
      pbch_pdu[2] = (pbch_pdu[2]&0xef) |
741 742
                    ((phy_vars_eNB->lte_frame_parms.phich_config_common.phich_duration << 4)&0x10);

743 744
      switch (phy_vars_eNB->lte_frame_parms.phich_config_common.phich_resource) {
      case oneSixth:
745
        pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (0<<2);
746 747
        break;

748
      case half:
749
        pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (1<<2);
750 751
        break;

752
      case one:
753
        pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (2<<2);
754 755
        break;

756
      case two:
757
        pbch_pdu[2] = (pbch_pdu[2]&0xf3) | (3<<2);
758 759
        break;

760
      default:
761
        // unreachable
762
        break;
763
      }
764

765 766 767
      pbch_pdu[2] = (pbch_pdu[2]&0xfc) | ((phy_vars_eNB->proc[sched_subframe].frame_tx>>8)&0x3);
      pbch_pdu[1] = phy_vars_eNB->proc[sched_subframe].frame_tx&0xfc;
      pbch_pdu[0] = 0;
768
    }
769

770 771
    /// First half of SSS (TDD)
    if (abstraction_flag==0) {
772

773
      if (phy_vars_eNB->lte_frame_parms.frame_type == TDD) {
774 775 776
        generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
                     AMP,
                     &phy_vars_eNB->lte_frame_parms,
777
                     (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5,
778
                     1);
779
      }
780
    }
781 782


783 784


785
    if (abstraction_flag==0) {
786

787
      generate_pbch(&phy_vars_eNB->lte_eNB_pbch,
788 789 790 791 792 793
                    phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
                    AMP,
                    &phy_vars_eNB->lte_frame_parms,
                    pbch_pdu,
                    phy_vars_eNB->proc[sched_subframe].frame_tx&3);

794
    }
795

796
#ifdef PHY_ABSTRACTION
797
    else {
798
      generate_pbch_emul(phy_vars_eNB,pbch_pdu);
799
    }
800

801
#endif
802 803


804
  }
805

806
  if (subframe == 1) {
807

808
    if (abstraction_flag==0) {
809

810
      if (phy_vars_eNB->lte_frame_parms.frame_type == TDD) {
811
        generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
812
                     AMP,
813 814 815
                     &phy_vars_eNB->lte_frame_parms,
                     2,
                     2);
816
      }
817
    }
818 819
  }

820 821
  // Second half of PSS/SSS (FDD)
  if (subframe == 5) {
822

823
    if (abstraction_flag==0) {
824

825
      if (phy_vars_eNB->lte_frame_parms.frame_type == FDD) {
826
        generate_pss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
827
                     AMP,
828
                     &phy_vars_eNB->lte_frame_parms,
829
                     (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5,
830 831
                     10);
        generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
832
                     AMP,
833
                     &phy_vars_eNB->lte_frame_parms,
834
                     (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 5 : 4,
835 836
                     10);

837
      }
838
    }
839
  }
840

841 842 843
  //  Second-half of SSS (TDD)
  if (subframe == 5) {
    if (abstraction_flag==0) {
844

845
      if (phy_vars_eNB->lte_frame_parms.frame_type == TDD) {
846 847 848
        generate_sss(phy_vars_eNB->lte_eNB_common_vars.txdataF[0],
                     AMP,
                     &phy_vars_eNB->lte_frame_parms,
849
                     (phy_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5,
850
                     11);
851
      }
852
    }