phy_procedures_lte_eNb.c 111 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
#include "assertions.h"
gauthier's avatar
gauthier committed
60
#include "msc.h"
61

62
#if defined(ENABLE_ITTI)
gauthier's avatar
For RAL    
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];
gauthier's avatar
gauthier committed
97
extern uint8_t smbv_frame_cnt;
98
99
100
101
102
103
#endif

#ifdef DIAG_PHY
extern int rx_sig_fifo;
#endif

knopp's avatar
knopp committed
104
uint8_t is_SR_subframe(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t UE_id)
105
{
knopp's avatar
   
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
{
gauthier's avatar
gauthier committed
160
  uint8_t i;
161

162
163

  LOG_D(PHY,"[eNB %d/%d] Adding UE with rnti %x\n",
164
165
        eNB->Mod_id,
        eNB->CC_id,
Cedric Roux's avatar
Cedric Roux committed
166
        (uint16_t)rnti);
167
168

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

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

196
int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) {
gauthier's avatar
gauthier committed
197
  uint8_t i;
198
  int j,CC_id;
199
  PHY_VARS_eNB *eNB;
200
201

  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
202
    eNB = PHY_vars_eNB_g[Mod_idP][CC_id];
203
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
204
      if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) {
205
206
207
208
	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 {
209
	if (eNB->UE_stats[i].crnti==rntiP) {
210
	  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Removed ue %"PRIx16" ", rntiP);
211
212
213

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

214
	  //LOG_D(PHY,("[PHY] UE_id %d\n",i);
215
216
217
218
	  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));
219
220
221
	  //  mac_exit_wrapper("Removing UE");
	  
	  /* clear the harq pid freelist */
222
223
	  eNB->dlsch[i][0]->head_freelist = 0;
	  eNB->dlsch[i][0]->tail_freelist = 0;
224
	  for (j = 0; j < 8; j++)
225
	    put_harq_pid_in_freelist(eNB->dlsch[i][0], j);
226
227
228
	  
	  return(i);
	}
229
      }
230
    }
231
  }
232
  MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (not found)", rntiP);
233
234
235
  return(-1);
}

236
int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
237
{
gauthier's avatar
gauthier committed
238
  uint8_t i;
239

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

250
251
252
  return(-1);
}

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

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

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

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

    for (i=0; i<DLSCH_ptr->Mdlharq; i++) {
      if (DLSCH_ptr->harq_processes[i]!=NULL) {
276
	if (DLSCH_ptr->harq_processes[i]->status == ACTIVE) {
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
	  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);
293
      }
294
    }
295
296
297
298
299
300
301
302

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

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

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

318
319
320
  return(0);
}

knopp's avatar
knopp committed
321
int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
322
{
323
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
324
325
}

knopp's avatar
knopp committed
326
327
int16_t get_target_pucch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
{
328
  return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUCCH;
knopp's avatar
knopp committed
329
330
}

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

}
#endif



knopp's avatar
knopp committed
340
void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type)
341
342
{
  UNUSED(r_type);
343
  int subframe = proc->subframe_rx;
344

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

349

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

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

knopp's avatar
   
knopp committed
363
364
#endif

365

366
367
}

knopp's avatar
   
knopp committed
368
369


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

gauthier's avatar
gauthier committed
374
375
  uint8_t aa;
  uint16_t last_subframe_emos;
376
  uint16_t pilot_pos1 = 3 - eNB->frame_parms.Ncp, pilot_pos2 = 10 - 2*eNB->frame_parms.Ncp;
gauthier's avatar
gauthier committed
377
  uint32_t bytes;
378
379
380

  last_subframe_emos=0;

knopp's avatar
   
knopp committed
381

knopp's avatar
   
knopp committed
382

knopp's avatar
   
knopp committed
383

384
#ifdef EMOS_CHANNEL
385

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

397
398
#endif

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

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

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


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

gauthier's avatar
For RAL    
gauthier committed
431

knopp's avatar
   
knopp committed
432

Cedric Roux's avatar
Cedric Roux committed
433
unsigned int taus(void);
knopp's avatar
   
knopp committed
434

knopp's avatar
knopp committed
435
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) {
436

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

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

knopp's avatar
knopp committed
515
void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstraction_flag) {
516

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

523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  // 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);
  }    
knopp's avatar
   
knopp committed
539

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

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

649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
  }
  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,
665
                     AMP,
666
                     &eNB->frame_parms,
667
668
669
670
                     (fp->Ncp==NORMAL) ? 6 : 5,
                     10);
        generate_sss(txdataF,
                     AMP,
671
                     &eNB->frame_parms,
672
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
                     (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);
  }

}

knopp's avatar
knopp committed
701
void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,const int UE_id) {
702

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

  // 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,
715
				       &eNB->dlsch_SI,
716
717
718
719
720
				       fp,
				       eNB->pdsch_config_dedicated,
				       SI_RNTI,
				       0,
				       P_RNTI,
721
				       eNB->UE_stats[0].DL_pmi_single);
722
723
    
    
724
    eNB->dlsch_SI->nCCE[subframe] = dci_alloc->firstCCE;
725
    
726
    LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
727
	  eNB->dlsch_SI->nCCE[subframe]);
728
729
730
731
    
#if defined(SMBV) 
    
    // configure SI DCI
732
733
    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);
734
735
736
737
738
739
740
741
742
743
744
745
746
747
      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,
748
				       &eNB->dlsch_ra,
749
750
751
752
753
				       fp,
				       eNB->pdsch_config_dedicated,
				       SI_RNTI,
				       dci_alloc->rnti,
				       P_RNTI,
754
				       eNB->UE_stats[0].DL_pmi_single);
755
756
    
    
757
    eNB->dlsch_ra->nCCE[subframe] = dci_alloc->firstCCE;
758
    
759
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA)  => %"PRIu8"\n",eNB->Mod_id,frame,subframe,
760
	  eNB->dlsch_ra->nCCE[subframe]);
761
762
763
#if defined(SMBV) 
    
    // configure RA DCI
764
765
    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);
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
      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
783
784
      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,
785
786
787
788
789
790
791
792
793
794
795
796
              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,
797
					 eNB->dlsch[(uint8_t)UE_id],
798
799
800
801
802
					 fp,
					 eNB->pdsch_config_dedicated,
					 SI_RNTI,
					 0,
					 P_RNTI,
803
					 eNB->UE_stats[(uint8_t)UE_id].DL_pmi_single);
804
      LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n",
805
	    eNB->Mod_id,dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->current_harq_pid,frame,subframe);
806
807
      
      
808
      eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
809
      
810
      LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16")  => %"PRIu8"/%u\n",eNB->Mod_id,frame,subframe,
811
	    dci_alloc->rnti,eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe]);
812
813
814
815
      
#if defined(SMBV) 
      
      // configure UE-spec DCI
816
817
      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);
818
	smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1,dci_alloc, i);
knopp's avatar
   
knopp committed
819
      }
820
821
822
823
824
      
#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,
825
	    frame, subframe,UE_id,
826
827
828
829
	    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",
830
	    eNB->Mod_id,frame,dci_alloc->rnti);
knopp's avatar
   
knopp committed
831
    }
832
833
834
  }
  
}
835

knopp's avatar
knopp committed
836
void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC_t *dci_alloc,const int UE_id) {
837

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

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

knopp's avatar
knopp committed
901
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) {
902

903
904
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
905
906
907
  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;
908
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
909
910
911
912
913
914
915
916
  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,
917
	frame, subframe, input_buffer_length,
918
919
920
921
922
	get_G(fp,
	      dlsch_harq->nb_rb,
	      dlsch_harq->rb_alloc,
	      get_Qm(dlsch_harq->mcs),
	      dlsch_harq->Nl,
knopp's avatar