phy_procedures_lte_eNb.c 72.6 KB
Newer Older
1
2
3
4
5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
Cédric Roux's avatar
Cédric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21
22
23

/*! \file phy_procedures_lte_eNB.c
 * \brief Implementation of eNB procedures from 36.213 LTE specifications
24
 * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
25
26
27
 * \date 2011
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
29
30
31
32
 * \note
 * \warning
 */

33
34
35
36
#include "PHY/defs_eNB.h"
#include "PHY/phy_extern.h"
#include "SCHED/sched_eNB.h"
#include "SCHED/sched_common_extern.h"
knopp's avatar
knopp committed
37
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
38
#include "nfapi_interface.h"
39
#include "fapi_l1.h"
40
41
42
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

43
44
#include "T.h"

45
#include "assertions.h"
gauthier's avatar
gauthier committed
46
#include "msc.h"
47

48
49
#include <time.h>

50
#if defined(ENABLE_ITTI)
gauthier's avatar
For RAL    
gauthier committed
51
#   include "intertask_interface.h"
52
53
#endif

54
extern uint8_t nfapi_mode;
55
56
57



58
int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t UE_id,uint8_t harq_pid, uint8_t bw_factor)
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
{

  uint32_t Nre,sumKr,MPR_x100,Kr,r;
  uint16_t beta_offset_pusch;

  DevAssert( UE_id < NUMBER_OF_UE_MAX+1 );
  DevAssert( harq_pid < 8 );

  Nre = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_initial *
        eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12;

  sumKr = 0;

  for (r=0; r<eNB->ulsch[UE_id]->harq_processes[harq_pid]->C; r++) {
    if (r<eNB->ulsch[UE_id]->harq_processes[harq_pid]->Cminus)
      Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kminus;
    else
      Kr = eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus;

    sumKr += Kr;
  }

  if (Nre==0)
    return(0);

  MPR_x100 = 100*sumKr/Nre;
  // Note: MPR=is the effective spectral efficiency of the PUSCH
  // FK 20140908 sumKr is only set after the ulsch_encoding

  beta_offset_pusch = 8;
  //(eNB->ulsch[UE_id]->harq_processes[harq_pid]->control_only == 1) ? eNB->ulsch[UE_id]->beta_offset_cqi_times8:8;

  DevAssert( UE_id < NUMBER_OF_UE_MAX );
//#warning "This condition happens sometimes. Need more investigation" // navid
  //DevAssert( MPR_x100/6 < 100 );

  if (1==1) { //eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled == 1) {
    // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch)
    if (bw_factor == 1) {
      uint8_t nb_rb = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb;
      return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)) + hundred_times_log10_NPRB[nb_rb-1];
    } else
      return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3));
  } else {
    return(0);
  }
}


int16_t get_hundred_times_delta_IF_mac(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t harq_pid)
{

  int8_t UE_id;

  if ((RC.eNB == NULL) || (module_idP > RC.nb_inst) || (CC_id > RC.nb_CC[module_idP])) {
    LOG_E(PHY,"get_UE_stats: No eNB found (or not allocated) for Mod_id %d,CC_id %d\n",module_idP,CC_id);
    return -1;
  }

  UE_id = find_ulsch( rnti, RC.eNB[module_idP][CC_id],SEARCH_EXIST);

  if (UE_id == -1) {
    // not found
    return 0;
  }

  return get_hundred_times_delta_IF_eNB( RC.eNB[module_idP][CC_id], UE_id, harq_pid, 0 );
}

128
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind);
129

knopp's avatar
   
knopp committed
130

131
132
lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subframe)
{
133

134
135
136
137
138
  return(subframe_select(&RC.eNB[Mod_id][CC_id]->frame_parms,subframe));

}

void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
139
140


141
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
knopp's avatar
knopp committed
142
  MCH_PDU *mch_pduP=NULL;
143
  //  uint8_t sync_area=255;
144
#endif
145

146
  int subframe = proc->subframe_tx;
147

knopp's avatar
knopp committed
148
149
  AssertFatal(1==0,"pmch not tested for the moment, exiting\n");

150
151
152
153
154
155
  // This is DL-Cell spec pilots in Control region
  generate_pilots_slot(eNB,
		       eNB->common_vars.txdataF,
		       AMP,
		       subframe<<1,1);

156
  
157
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
158
159
  // 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
160
  /*
161
162
  mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id,
				    eNB->CC_id,
163
				    proc->frame_tx,
164
				    subframe);
165
  */
166
167
168
169
170
171
172
173
174
175
  if ((mch_pduP->Pdu_size > 0) && (mch_pduP->sync_area == 0)) // TEST: only transmit mcch for sync area 0
    LOG_D(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (MCS %"PRIu8", TBS %d) \n",
	  eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs,
	  eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
  else {
    LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n",
	  eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->sync_area,
	  (mch_pduP->Pdu_size == 0)? "Empty MCH PDU":"Let RN transmit for the moment");
    mch_pduP = NULL;
  }
176
177
    
  if (mch_pduP) {
178
    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0);
179
    // Generate PMCH
180
    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload);
181
  } else {
182
    LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe);
knopp's avatar
   
knopp committed
183
  }
184
  
185
#endif
186
}
187

188
void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
189

190
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
191
  int **txdataF = eNB->common_vars.txdataF;
192
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
193

194
  //LOG_D(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?"); 
195

196
  // generate Cell-Specific Reference Signals for both slots
197
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
198
199
200
201
202
203
204

   if(subframe_select(fp,subframe) == SF_S)
       generate_pilots_slot(eNB,
                    txdataF,
                    AMP,
                    subframe<<1,1);
   else
205
206
207
208
  generate_pilots_slot(eNB,
		       txdataF,
		       AMP,
		       subframe<<1,0);
209
210
211

 // check that 2nd slot is for DL

212
213
  // check that 2nd slot is for DL
  if (subframe_select(fp,subframe) == SF_DL)
214
215
216
    generate_pilots_slot(eNB,
			 txdataF,
			 AMP,
217
218
219
220
			 (subframe<<1)+1,0);
  
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,0);
      
221

222
  // First half of PSS/SSS (FDD, slot 0)
knopp's avatar
   
knopp committed
223
  if (subframe == 0) {
224
    if (fp->frame_type == FDD) {
225
226
227
228
229
230
231
232
233
234
235
      generate_pss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   0);
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 5 : 4,
		   0);
      
236
    }
237
    
238
239


240
241
242
      
    /// First half of SSS (TDD, slot 1)
    
243
    if (fp->frame_type == TDD) {
244
245
246
247
248
249
      generate_sss(txdataF,
		   AMP,
		   fp,
		   (fp->Ncp==NORMAL) ? 6 : 5,
		   1);
    }
250

251
252
    // generate PBCH (Physical Broadcast CHannel) info

253
    /// generate PBCH
254
    if ((frame&3)==0) {
255
256
      //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n");
      if (eNB->pbch_configured!=1) return;
257
      eNB->pbch_configured=0;
258
    }
259
260
261
262
263
264
265
    generate_pbch(&eNB->pbch,
		  txdataF,
		  AMP,
		  fp,
		  pbch_pdu,
		  frame&3);
  
266
  }
267
  else if ((subframe == 1) &&
268
	   (fp->frame_type == TDD)){
269
270
271
272
273
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 2);
274
  }
275
276
277
  
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && 
278
	   (fp->frame_type == FDD)) {
279
280
281
282
283
284
285
286
287
288
    generate_pss(txdataF,
		 AMP,
		 &eNB->frame_parms,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 10);
    generate_sss(txdataF,
		 AMP,
		 &eNB->frame_parms,
		 (fp->Ncp==NORMAL) ? 5 : 4,
		 10);
289

290
  }
291

292
293
  //  Second-half of SSS (TDD, slot 11)
  else if ((subframe == 5) &&
294
	   (fp->frame_type == TDD)) {
295
296
297
298
299
    generate_sss(txdataF,
		 AMP,
		 fp,
		 (fp->Ncp==NORMAL) ? 6 : 5,
		 11);
knopp's avatar
   
knopp committed
300
  }
knopp's avatar
   
knopp committed
301

302
303
  // Second half of PSS (TDD, slot 12)
  else if ((subframe == 6) &&
304
	   (fp->frame_type == TDD)) { 
305
306
307
308
309
310
    generate_pss(txdataF,
		 AMP,
		 fp,
		 2,
		 12);
  }
knopp's avatar
   
knopp committed
311

312
}
knopp's avatar
   
knopp committed
313

314
315


316
317
318
319
320
321
void pdsch_procedures(PHY_VARS_eNB *eNB,
		      eNB_rxtx_proc_t *proc,
		      int harq_pid,
		      LTE_eNB_DLSCH_t *dlsch, 
		      LTE_eNB_DLSCH_t *dlsch1,
		      LTE_eNB_UE_stats *ue_stats,
322
		      int ra_flag) {
323

324
325
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
326
327
  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
  int input_buffer_length = dlsch_harq->TBS/8;
328
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
329

330
  if (dlsch->rnti == 0x02) {//frame < 200) {
331

332
    LOG_D(PHY,
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
	  "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", pdsch_start %d, G %d, nb_rb %"PRIu16", rb0 %x, rb1 %x, TBS %"PRIu16", pmi_alloc %"PRIx64", rv %"PRIu8" (round %"PRIu8")\n",
	  eNB->Mod_id, dlsch->rnti,harq_pid,
	  frame, subframe, input_buffer_length, dlsch_harq->pdsch_start,
	  get_G(fp,
		dlsch_harq->nb_rb,
		dlsch_harq->rb_alloc,
		dlsch_harq->Qm,
		dlsch_harq->Nl,
		dlsch_harq->pdsch_start,
		frame,
		subframe,
		dlsch_harq->mimo_mode==TM7?7:0),
	  dlsch_harq->nb_rb,
	  dlsch_harq->rb_alloc[0],
	  dlsch_harq->rb_alloc[1],
	  dlsch_harq->TBS,
	  pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
	  dlsch_harq->rvidx,
	  dlsch_harq->round);
  }    
353
#if defined(MESSAGE_CHART_GENERATOR_PHY)
354
355
356
  MSC_LOG_TX_MESSAGE(
		     MSC_PHY_ENB,MSC_PHY_UE,
		     NULL,0,
357
		     "%05u:%02u PDSCH/DLSCH input size = %"PRIu16", G %d, nb_rb %"PRIu16", TBS %"PRIu16", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")",
358
359
360
361
362
		     frame, subframe,
		     input_buffer_length,
		     get_G(fp,
			   dlsch_harq->nb_rb,
			   dlsch_harq->rb_alloc,
363
			   dlsch_harq->Qm,
364
			   dlsch_harq->Nl,
365
			   dlsch_harq->pdsch_start,
366
367
368
			   frame,
			   subframe,
			   dlsch_harq->mimo_mode==TM7?7:0),
369
		     dlsch_harq->nb_rb,
370
		     dlsch_harq->TBS,
371
372
373
374
		     pmi2hex_2Ar1(dlsch_harq->pmi_alloc),
		     dlsch_harq->rvidx,
		     dlsch_harq->round);
#endif
375
376
  
  
377
  if (ue_stats) ue_stats->dlsch_sliding_cnt++;
378
  
379
380
381
  if (dlsch_harq->round == 0) {
    if (ue_stats)
      ue_stats->dlsch_trials[harq_pid][0]++;
382
383
384
385
386
387
388
389
  } 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
  }
390
391


392
393
  LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n",
      dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0],dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round);
394
  // 36-212 
395
396
397
398
399
400
401
402
403
404
  if (nfapi_mode == 0 || nfapi_mode == 1) { // monolthic OR PNF - do not need turbo encoding on VNF

    if (dlsch_harq->pdu==NULL){
        LOG_E(PHY,"dlsch_harq->pdu == NULL SFN/SF:%04d%d dlsch[rnti:%x] dlsch_harq[pdu:%p pdsch_start:%d Qm:%d Nl:%d round:%d nb_rb:%d rb_alloc[0]:%d]\n", frame,subframe,dlsch->rnti, dlsch_harq->pdu,dlsch_harq->pdsch_start,dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0]);
      return;
    }

    start_meas(&eNB->dlsch_encoding_stats);

    eNB->te(eNB,
405
	  dlsch_harq->pdu,
406
	  dlsch_harq->pdsch_start,
407
	  dlsch,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
408
409
	  frame,
	  subframe,
410
411
	  &eNB->dlsch_rate_matching_stats,
	  &eNB->dlsch_turbo_encoding_stats,
Wang Tsu-Han's avatar
Wang Tsu-Han committed
412
	  &eNB->dlsch_turbo_encoding_waiting_stats,
413
      &eNB->dlsch_turbo_encoding_main_stats,
414
415
      &eNB->dlsch_turbo_encoding_wakeup_stats0,
      &eNB->dlsch_turbo_encoding_wakeup_stats1,
416
	  &eNB->dlsch_interleaving_stats);
417
    stop_meas(&eNB->dlsch_encoding_stats);
418
419
420
421
422
  //////////////////////////////////////////////////*******************************************
  if(eNB->dlsch_encoding_stats.diff_now>500*3000 && opp_enabled == 1)
  {
    print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
  }
423
  // 36-211
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
    start_meas(&eNB->dlsch_scrambling_stats);
    dlsch_scrambling(fp,
        0,
        dlsch,
        harq_pid,
        get_G(fp,
          dlsch_harq->nb_rb,
          dlsch_harq->rb_alloc,
          dlsch_harq->Qm,
          dlsch_harq->Nl,
          dlsch_harq->pdsch_start,
          frame,subframe,
          0),
        0,
        frame,
        subframe<<1);
    stop_meas(&eNB->dlsch_scrambling_stats);

    start_meas(&eNB->dlsch_modulation_stats);

444
  
445
    dlsch_modulation(eNB,
446
447
		   eNB->common_vars.txdataF,
		   AMP,
jftt_wangshanshan's avatar
jftt_wangshanshan committed
448
		   frame,
449
		   subframe,
450
		   dlsch_harq->pdsch_start,
451
452
453
454
		   dlsch,
		   dlsch1);
  
  stop_meas(&eNB->dlsch_modulation_stats);
455
  }
456
#ifdef PHY_TX_THREAD
457
458
  dlsch->active[subframe] = 0;
#else
459
  dlsch->active = 0;
460
#endif
461
  dlsch_harq->round++;
462
463

  LOG_D(PHY,"Generating DLSCH/PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
464
}
465
466


467

knopp's avatar
knopp committed
468

469
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
knopp's avatar
knopp committed
470
			   eNB_rxtx_proc_t *proc,
471
			   int do_meas)
472
{
473
474
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
475
  uint32_t i,aa;
476
  uint8_t harq_pid;
477
  int16_t UE_id=0;
478
  uint8_t num_pdcch_symbols=0;
479
  uint8_t num_dci=0;
480
481
  uint8_t ul_subframe;
  uint32_t ul_frame;
482
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
483
  LTE_UL_eNB_HARQ_t *ulsch_harq;
484

485
  int offset = eNB->CC_id;//proc == &eNB->proc.proc_rxtx[0] ? 0 : 1;
486

knopp's avatar
knopp committed
487

488
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)==SF_UL)) return;
489

Raymond Knopp's avatar
Raymond Knopp committed
490
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
491
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
492

493
  // clear the transmit data array for the current subframe
494
495
496
  for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {      
    memset(&eNB->common_vars.txdataF[aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
	   0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
knopp's avatar
   
knopp committed
497
  }
498
  
499

knopp's avatar
knopp committed
500

501
502
  if (nfapi_mode == 0 || nfapi_mode == 1) {
    if (is_pmch_subframe(frame,subframe,fp)) {
503
      pmch_procedures(eNB,proc);
504
505
506
507
508
    }
    else {
      // this is not a pmch subframe, so generate PSS/SSS/PBCH
      common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx);
    }
509
  }
510

knopp's avatar
knopp committed
511

knopp's avatar
   
knopp committed
512
  // clear existing ulsch dci allocations before applying info from MAC  (this is table
513
  ul_subframe = pdcch_alloc2ul_subframe(fp,subframe);
514
  ul_frame = pdcch_alloc2ul_frame(fp,frame,subframe);
515
516
517



knopp's avatar
   
knopp committed
518
  // clear previous allocation information for all UEs
519
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
520
521
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
knopp's avatar
   
knopp committed
522
  }
523

524
  /* save old HARQ information needed for PHICH generation */
525
526
527
528
  /* TODO: check the following test - in the meantime it is put back as it was before */
  //if ((ul_subframe < 10)&&
  //    (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here
  if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
      harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
      if (eNB->ulsch[i]) {
	ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid];
	
	/* Store first_rb and n_DMRS for correct PHICH generation below.
	 * For PHICH generation we need "old" values of last scheduling
	 * for this HARQ process. 'generate_eNB_dlsch_params' below will
	 * overwrite first_rb and n_DMRS and 'generate_phich_top', done
	 * after 'generate_eNB_dlsch_params', would use the "new" values
	 * instead of the "old" ones.
	 *
	 * This has been tested for FDD only, may be wrong for TDD.
	 *
	 * TODO: maybe we should restructure the code to be sure it
	 *       is done correctly. The main concern is if the code
	 *       changes and first_rb and n_DMRS are modified before
	 *       we reach here, then the PHICH processing will be wrong,
	 *       using wrong first_rb and n_DMRS values to compute
	 *       ngroup_PHICH and nseq_PHICH.
	 *
	 * TODO: check if that works with TDD.
	 */
	ulsch_harq->previous_first_rb = ulsch_harq->first_rb;
	ulsch_harq->previous_n_DMRS   = ulsch_harq->n_DMRS;
	
555
556
557
558
      }
    }
  }

559

560

561
562
  num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols;
  num_dci           = eNB->pdcch_vars[subframe&1].num_dci;
Cédric Roux's avatar
Cédric Roux committed
563
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci);
564
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
565

566

567
568
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);

569
  if (num_dci > 0)
570
    LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %"PRIu8") num_pdcch_symbols:%d\n",eNB->Mod_id,frame, subframe, num_dci, num_pdcch_symbols);
Cédric Roux's avatar
Cédric Roux committed
571

572
573
574
575
576
577
578
579
580
581
582
583
584

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);

  if (nfapi_mode == 0 || nfapi_mode == 1) {
    generate_dci_top(num_pdcch_symbols,
        num_dci,
        &eNB->pdcch_vars[subframe&1].dci_alloc[0],
        0,
        AMP,
        fp,
        eNB->common_vars.txdataF,
        subframe);
  }
585

586

gauthier's avatar
gauthier committed
587
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
588

589
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
knopp's avatar
   
knopp committed
590
  // Now scan UE specific DLSCH
591
  LTE_eNB_DLSCH_t *dlsch0,*dlsch1;
592
  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
593
    {
594
595
596
597
598
      dlsch0 = eNB->dlsch[(uint8_t)UE_id][0]; 
      dlsch1 = eNB->dlsch[(uint8_t)UE_id][1]; 

      if ((dlsch0)&&
	  (dlsch0->rnti>0)&&
599
#ifdef PHY_TX_THREAD
600
601
	  (dlsch0->active[subframe] == 1)) {
#else
602
	  (dlsch0->active == 1)) {
603
#endif
604

605
	// get harq_pid
jftt_wangshanshan's avatar
jftt_wangshanshan committed
606
	harq_pid = dlsch0->harq_ids[frame%2][subframe];
607
	AssertFatal(harq_pid>=0,"harq_pid is negative\n");
608
609
610
611
612
613
614
615

        if (harq_pid>=8)
        {
          LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x\n", harq_pid,UE_id,frame,subframe,dlsch0->rnti);
        }
        else
        {
          // generate pdsch
knopp's avatar
knopp committed
616

617
618
619
620
621
622
623
624
          pdsch_procedures(eNB,
              proc,
              harq_pid,
              dlsch0,
              dlsch1,
              &eNB->UE_stats[(uint32_t)UE_id],
              0);
        }
625
626


knopp's avatar
   
knopp committed
627
      }
628

gauthier's avatar
gauthier committed
629

630
631
      else if ((dlsch0)&&
	       (dlsch0->rnti>0)&&
632
#ifdef PHY_TX_THREAD
633
634
635
636
	       (dlsch0->active[subframe] == 0)) {
#else
           (dlsch0->active == 0)) {
#endif
637

638
639
        // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
        dlsch0->subframe_tx[subframe]=0;
knopp's avatar
   
knopp committed
640
      }
knopp's avatar
   
knopp committed
641
    }
642
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
643

644
645


646
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,1);
647
648
649
  generate_phich_top(eNB,
		     proc,
		     AMP);
650
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,0);
651

Raymond Knopp's avatar
Raymond Knopp committed
652
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,0);
653
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
654
  
655
656
}

657

658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
void srs_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {

  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;

  int i;

  if (is_srs_occasion_common(fp,frame,subframe)) { 
  
  // Do SRS processing 
  // check if there is SRS and we have to use shortened format
  // TODO: check for exceptions in transmission of SRS together with ACK/NACK
    for (i=0;i<NUMBER_OF_UE_MAX;i++) {

      if (eNB->soundingrs_ul_config_dedicated[i].active==1) {

      
	if (lte_srs_channel_estimation(fp,
				       &eNB->common_vars,
				       &eNB->srs_vars[i],
				       &eNB->soundingrs_ul_config_dedicated[i],
				       subframe,
				       0/*eNB_id*/)) {
	  LOG_E(PHY,"problem processing SRS\n");
	}
	eNB->soundingrs_ul_config_dedicated[i].active=0;
      }
    }
  }
}

690
691
void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) {
  
692
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
693
694
695
696
697
698
699
700
  nfapi_sr_indication_t       *sr_ind =         &eNB->UL_INFO.sr_ind;
  nfapi_sr_indication_body_t  *sr_ind_body =    &sr_ind->sr_indication_body;
  nfapi_sr_indication_pdu_t *pdu =   &sr_ind_body->sr_pdu_list[sr_ind_body->number_of_srs];

  sr_ind->sfn_sf = frame<<4|subframe;
  sr_ind->header.message_id = NFAPI_RX_SR_INDICATION;

  sr_ind_body->tl.tag = NFAPI_SR_INDICATION_BODY_TAG;
701
702
703

  pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
704
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
705
706
  pdu->rx_ue_information.rnti                         = rnti;

707
  int SNRtimes10 = dB_fixed_times10(stat) - 300;//(10*eNB->measurements.n0_power_dB[0]);
708
709


710
711
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;

712
713
714
715
716
  if      (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0;
  else if (SNRtimes10 >  635) pdu->ul_cqi_information.ul_cqi=255;
  else                        pdu->ul_cqi_information.ul_cqi=(640+SNRtimes10)/5;
  pdu->ul_cqi_information.channel = 0;

717
  sr_ind_body->number_of_srs++;
718
719
720
721
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}

void uci_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
Cédric Roux's avatar
Cédric Roux committed
722
{
723
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
724
  uint8_t SR_payload = 0,pucch_b0b1[4][2]= {{0,0},{0,0},{0,0},{0,0}},harq_ack[4]={0,0,0,0};
725
  int32_t metric[4]={0,0,0,0},metric_SR=0,max_metric=0;
726
727
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
728
729
730
731
  int i;
  LTE_eNB_UCI *uci;
  uint16_t tdd_multiplexing_mask=0;
  int res;
732

733
  for (i=0;i<NUMBER_OF_UE_MAX;i++) {
Cédric Roux's avatar
Cédric Roux committed
734

735
736
737
738
    uci = &eNB->uci_vars[i];
    if ((uci->active == 1) &&
	(uci->frame == frame) &&
	(uci->subframe == subframe)) {
739

740
      LOG_D(PHY,"Frame %d, subframe %d: Running uci procedures (type %d) for %d \n",frame,subframe,uci->type,i);
741
      uci->active=0;
Cédric Roux's avatar
Cédric Roux committed
742

knopp's avatar
knopp committed
743
744
745
      // Null out PUCCH PRBs for noise measurement
      switch(fp->N_RB_UL) {
      case 6:
Cédric Roux's avatar
Cédric Roux committed
746
747
        eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5
        break;
knopp's avatar
knopp committed
748
      case 15:
Cédric Roux's avatar
Cédric Roux committed
749
750
        eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14
        break;
knopp's avatar
knopp committed
751
      case 25:
Cédric Roux's avatar
Cédric Roux committed
752
753
        eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24
        break;
knopp's avatar
knopp committed
754
      case 50:
Cédric Roux's avatar
Cédric Roux committed
755
756
757
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32)
        break;
knopp's avatar
knopp committed
758
      case 75:
Cédric Roux's avatar
Cédric Roux committed
759
760
761
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64)
        break;
knopp's avatar
knopp committed
762
      case 100:
Cédric Roux's avatar
Cédric Roux committed
763
764
765
        eNB->rb_mask_ul[0] |= 0x1;
        eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96)
        break;
knopp's avatar
knopp committed
766
      default:
Cédric Roux's avatar
Cédric Roux committed
767
768
        LOG_E(PHY,"Unknown number for N_RB_UL %d\n",fp->N_RB_UL);
        break;
knopp's avatar
knopp committed
769
      }
Wu Jing's avatar
Wu Jing committed
770
      SR_payload = 0;
771
772
773
774
775
      switch (uci->type) {
      case SR:
      case HARQ_SR:
		
	metric_SR = rx_pucch(eNB,
776
777
778
779
780
781
782
783
784
			     uci->pucch_fmt,
			     i,
			     uci->n_pucch_1_0_sr[0],
			     0, // n2_pucch
			     uci->srs_active, // shortened format
			     &SR_payload,
			     frame,
			     subframe,
			     PUCCH1_THRES);
785
	LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (uci.type %d SR n1pucch is %d)\n",
786
	      eNB->Mod_id,
787
	      uci->rnti,
788
789
790
	      frame,
	      subframe,
	      SR_payload,
791
              uci->type,
792
793
794
	      uci->n_pucch_1_0_sr[0]);
	if (uci->type == SR) {
	  if (SR_payload == 1) {
795
	    fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
796
	    break;
797
798
	  }
	  else {
799
	    break;
800
801
802
803
	  }
	}
      case HARQ:
	if (fp->frame_type == FDD) {
804
	  LOG_D(PHY,"Frame %d Subframe %d Demodulating PUCCH (UCI %d) for ACK/NAK (uci->pucch_fmt %d,uci->type %d.uci->frame %d, uci->subframe %d): n1_pucch0 %d SR_payload %d\n",
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
		frame,subframe,i,
		uci->pucch_fmt,uci->type,
		uci->frame,uci->subframe,uci->n_pucch_1[0][0],
		SR_payload);
	  
	  metric[0] = rx_pucch(eNB,
			       uci->pucch_fmt,
			       i,
			       uci->n_pucch_1[0][0],
			       0, //n2_pucch
			       uci->srs_active, // shortened format
			       pucch_b0b1[0],
			       frame,
			       subframe,
			       PUCCH1a_THRES);
	  
	  
	  /* cancel SR detection if reception on n1_pucch0 is better than on SR PUCCH resource index, otherwise send it up to MAC */
	  if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0;
824
	  else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
 
	  if (uci->type==HARQ_SR && metric[0] <= metric_SR) {
	    /* when transmitting ACK/NACK on SR PUCCH resource index, SR payload is always 1 */
	    SR_payload = 1;
	    
	    metric[0]=rx_pucch(eNB,
			       uci->pucch_fmt,
			       i,
			       uci->n_pucch_1_0_sr[0],
			       0, //n2_pucch
			       uci->srs_active, // shortened format
			       pucch_b0b1[0],
			       frame,
			       subframe,
			       PUCCH1a_THRES);
	  }
	  
842

843
	  LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
844
845
846
		eNB->Mod_id,
		uci->rnti,
		frame,subframe,
847
848
		pucch_b0b1[0][0],metric[0]);

849
	  uci->stat = metric[0]; 	  
850
	  fill_uci_harq_indication(eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff);
851

852
853
	}
	else { // frame_type == TDD
854
855
856
857
858
	  LOG_D(PHY,"Frame %d Subframe %d Demodulating PUCCH (UCI %d) for ACK/NAK (uci->pucch_fmt %d,uci->type %d.uci->frame %d, uci->subframe %d): n1_pucch0 %d SR_payload %d\n",
		frame,subframe,i,
		uci->pucch_fmt,uci->type,
		uci->frame,uci->subframe,uci->n_pucch_1[0][0],
		SR_payload);
859
860
#if 1
	      metric[0] = rx_pucch(eNB,
861
862
863
864
865
866
867
868
869
				   uci->pucch_fmt,
				   i,
				   uci->n_pucch_1[0][0],
				   0, //n2_pucch
				   uci->srs_active, // shortened format
				   pucch_b0b1[0],
				   frame,
				   subframe,
				   PUCCH1a_THRES);
870
871
872
873
874
875
	      if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0;
	      else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR);

	      if (uci->type==HARQ_SR && metric[0] <= metric_SR) {
	          SR_payload = 1;
	          metric[0] = rx_pucch(eNB,
876
877
878
879
880
881
882
883
884
				       pucch_format1b,
				       i,
				       uci->n_pucch_1_0_sr[0],
				       0, //n2_pucch
				       uci->srs_active, // shortened format
				       pucch_b0b1[0],
				       frame,
				       subframe,
				       PUCCH1a_THRES);
885
886
	      }
#else
887
888
	  // if SR was detected, use the n1_pucch from SR
	  if (SR_payload==1) {
889
#ifdef DEBUG_PHY_PROC
890
891
892
893
	    LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK (%d,%d,%d,%d) format %d with SR\n",eNB->Mod_id,
		  eNB->dlsch[UE_id][0]->rnti,
		  frame,subframe,
		  n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
894
#endif
895
896
897
898
899
900
901
902
903
904
905
906
	    
	    metric[0] = rx_pucch(eNB,
				 pucch_format1b,
				 i,
				 uci->n_pucch_1_0_sr[0],
				 0, //n2_pucch
				 uci->srs_active, // shortened format
				 pucch_b0b1[0],
				 frame,
				 subframe,
				 PUCCH1a_THRES);
	  } else { //using assigned pucch resources
907
#ifdef DEBUG_PHY_PROC
908
909
910
911
912
913
914
915
916
	    LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d Checking ACK/NAK M=%d (%d,%d,%d,%d) format %d\n",eNB->Mod_id,
		  eNB->dlsch[UE_id][0]->rnti,
		  frame,subframe,
		  uci->num_pucch_resources,
		  uci->n_pucch_1[res][0],
		  uci->n_pucch_1[res][1],
		  uci->n_pucch_1[res][2],
		  uci->n_pucch_1[res][3],
		  uci->pucch_fmt);
917
#endif
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
	    for (res=0;res<uci->num_pucch_resources;res++)
	      metric[res] = rx_pucch(eNB,
				     uci->pucch_fmt,
				     i,
				     uci->n_pucch_1[res][0],
				     0, // n2_pucch
				     uci->srs_active, // shortened format
				     pucch_b0b1[res],
				     frame,
				     subframe,
				     PUCCH1a_THRES);
	  	  
	    

	  }
Haruki Naoi's avatar
Haruki Naoi committed
933
934
#ifdef DEBUG_PHY_PROC
 	      LOG_D(PHY,"RNTI %x type %d SR_payload %d  Frame %d Subframe %d  pucch_b0b1[0][0] %d pucch_b0b1[0][1] %d pucch_b0b1[1][0] %d pucch_b0b1[1][1] %d  \n",
935
	              uci->rnti,uci->type,SR_payload,frame,subframe,pucch_b0b1[0][0],pucch_b0b1[0][1],pucch_b0b1[1][0],pucch_b0b1[1][1]);
Haruki Naoi's avatar
Haruki Naoi committed
936
937
#endif
#endif
938
939
940
941
	  if (SR_payload == 1) { // this implements Table 7.3.1 from 36.213
	    if (pucch_b0b1[0][0] == 4) { // there isn't a likely transmission
	      harq_ack[0] = 4; // DTX
	    }
942
	    else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1) { // 1/4/7 ACKs
943
944
	      harq_ack[0] = 1;
	    }
945
	    else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] != 1) { // 2/5/8 ACKs
946
947
	      harq_ack[0] = 2;
	    }
948
	    else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] == 1) { // 3/6/9 ACKs
949
950
	      harq_ack[0] = 3;
	    }
951
	    else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] != 1) { // 0 ACKs, or at least one DL assignment missed
952
953
	      harq_ack[0] = 0;
	    }
954
	    uci->stat = metric[0];
955
956
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode
	  } 
knopp's avatar
knopp committed
957
	  else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==2)){ // multiplexing + no SR, implement Table 10.1.3-5 (Rel14) for multiplexing with M=2
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
	    if (pucch_b0b1[0][0] == 4 ||
		pucch_b0b1[1][0] == 4) { // there isn't a likely transmission
	      harq_ack[0] = 4; // DTX
	      harq_ack[1] = 6; // NACK/DTX
	    } 
	    else {
	      if (metric[1]>metric[0]) {
		if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] != 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 1; // ACK
		  tdd_multiplexing_mask = 0x3;
		}
		else if (pucch_b0b1[1][0] != 1 && pucch_b0b1[1][1] == 1){
		  harq_ack[0] = 6; // NACK/DTX
		  harq_ack[1] = 1; // ACK
		  tdd_multiplexing_mask = 0x2;
		}
		else {
		  harq_ack[0] = 4; // DTX
		  harq_ack[1] = 4; // DTX
		}
	      }
	      else {
		if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1){
		  harq_ack[0] = 1; // ACK
		  harq_ack[1] = 6; // NACK/DTX
		  tdd_multiplexing_mask = 0x1;
		}
		else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] != 1){
		  harq_ack[0] = 2; // NACK
		  harq_ack[1] = 6; // NACK/DTX
		}
		else {
		  harq_ack[0] = 4; // DTX
		  harq_ack[1] = 4; // DTX
		}
	      }
	    }
996
	    uci->stat = max(metric[0],metric[1]);
997
	    fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
knopp's avatar
knopp committed
998
	  } //else if ((uci->tdd_bundling == 0) && (res==2))
knopp's avatar
knopp committed
999
	  else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==3)){ // multiplexing + no SR, implement Table 10.1.3-6 (Rel14) for multiplexing with M=3
1000
	    
For faster browsing, not all history is shown. View entire blame