phy_procedures_lte_eNb.c 95 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
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

/*! \file phy_procedures_lte_eNB.c
23 24
 * \brief Implementation of eNB procedures from 36.213 LTE specifications / FeMBMS 36.231 LTE procedures v14.2
 * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas, J. Morgade
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, javier.morgade@ieee.org
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"
37
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
frtabu's avatar
frtabu committed
38
#include "nfapi/oai_integration/vendor_ext.h"
39
#include "fapi_l1.h"
40
#include "common/utils/LOG/log.h"
Laurent's avatar
Laurent committed
41
#include <common/utils/system.h>
42
#include "common/utils/LOG/vcd_signal_dumper.h"
43

44
#include "assertions.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
45
#include "msc.h"
46

47 48
#include <time.h>

Raymond Knopp's avatar
Raymond Knopp committed
49
#include "intertask_interface.h"
50
#include <executables/split_headers.h> 
51

52 53
#define MBMS_NFAPI_SCHEDULER

Raymond Knopp's avatar
Raymond Knopp committed
54 55 56
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;

57
nfapi_ue_release_request_body_t release_rntis;
58

59
int16_t get_hundred_times_delta_IF_eNB(PHY_VARS_eNB *eNB,uint16_t ULSCH_id,uint8_t harq_pid, uint8_t bw_factor) {
60 61
  uint32_t Nre,sumKr,MPR_x100,Kr,r;
  uint16_t beta_offset_pusch;
62
  DevAssert( ULSCH_id < NUMBER_OF_ULSCH_MAX+1 );
63
  DevAssert( harq_pid < 8 );
64 65
  Nre = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->Nsymb_initial *
        eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->nb_rb*12;
66 67
  sumKr = 0;

68 69 70
  for (r=0; r<eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->C; r++) {
    if (r<eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->Cminus)
      Kr = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->Kminus;
71
    else
72
      Kr = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->Kplus;
73 74 75 76 77 78 79 80 81 82 83 84

    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;
85
  DevAssert( ULSCH_id < NUMBER_OF_ULSCH_MAX );
86
  //#warning "This condition happens sometimes. Need more investigation" // navid
87 88 89 90 91
  //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) {
92
      uint8_t nb_rb = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->nb_rb;
93 94 95 96 97 98 99 100 101
      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);
  }
}


frtabu's avatar
frtabu committed
102
int16_t get_hundred_times_delta_IF_mac(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t harq_pid) {
103
  int8_t ULSCH_id;
104 105 106 107 108 109

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

110
  ULSCH_id = find_ulsch( rnti, RC.eNB[module_idP][CC_id],SEARCH_EXIST);
111

112
  if (ULSCH_id == -1) {
113 114 115 116
    // not found
    return 0;
  }

117
  return get_hundred_times_delta_IF_eNB( RC.eNB[module_idP][CC_id], ULSCH_id, harq_pid, 0 );
118 119
}

120
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind);
121

Raymond Knopp's avatar
 
Raymond Knopp committed
122

frtabu's avatar
frtabu committed
123
lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subframe) {
124 125
  return(subframe_select(&RC.eNB[Mod_id][CC_id]->frame_parms,subframe));
}
126

127
#ifdef MBMS_NFAPI_SCHEDULER
128
void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, int fembms_flag) {
129 130
  int subframe = proc->subframe_tx;
  // This is DL-Cell spec pilots in Control region
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
  if(!fembms_flag){
  	generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1);
 	generate_mbsfn_pilot(eNB,proc,
                       eNB->common_vars.txdataF,
                       AMP);
  }else
	generate_mbsfn_pilot_khz_1dot25(eNB,proc,
                       eNB->common_vars.txdataF,
                       AMP);

  if(eNB->dlsch_MCH->active==1){
	if(!fembms_flag){
  	  generate_mch (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/);
        }
        else{
 	  generate_mch_khz_1dot25 (eNB, proc,NULL/*, eNB->dlsch_MCH->harq_processes[0]->pdu*/);
        }

    	  LOG_D(PHY,"[eNB%"PRIu8"] Frame %d subframe %d : Got MCH pdu for MBSFN (TBS %d) fembms %d \n",
          eNB->Mod_id,proc->frame_tx,subframe,
          eNB->dlsch_MCH->harq_processes[0]->TBS>>3,fembms_flag);

  }
154 155 156
  eNB->dlsch_MCH->active = 0;
}
#else
157
void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
Raymond Knopp's avatar
Raymond Knopp committed
158
  MCH_PDU *mch_pduP=NULL;
159
  //  uint8_t sync_area=255;
Raymond Knopp's avatar
Raymond Knopp committed
160
  int             subframe = proc->subframe_tx;
161
  AssertFatal (1 == 1, "pmch not tested for the moment, exiting\n");
162
  // This is DL-Cell spec pilots in Control region
Raymond Knopp's avatar
Raymond Knopp committed
163
  generate_pilots_slot (eNB, eNB->common_vars.txdataF, AMP, subframe << 1, 1);
frtabu's avatar
frtabu committed
164

165 166
  // 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
167
  /*
168 169 170 171 172
    mch_pduP = mac_xface->get_mch_sdu(eNB->Mod_id,
    eNB->CC_id,
    proc->frame_tx,
    subframe);
  */
173
  mch_pduP= &RC.mac[eNB->Mod_id]->common_channels[eNB->CC_id].MCH_pdu;
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",
frtabu's avatar
frtabu committed
176 177
          eNB->Mod_id,proc->frame_tx,subframe,mch_pduP->mcs,
          eNB->dlsch_MCH->harq_processes[0]->TBS>>3);
178 179
  else {
    LOG_D(PHY,"[DeNB %"PRIu8"] Frame %d subframe %d : Do not transmit MCH pdu for MBSFN sync area %"PRIu8" (%s)\n",
frtabu's avatar
frtabu committed
180 181
          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");
Raymond Knopp's avatar
Raymond Knopp committed
182
    mch_pduP = NULL;
183
  }
frtabu's avatar
frtabu committed
184

185
  if (mch_pduP) {
Raymond Knopp's avatar
Raymond Knopp committed
186
    fill_eNB_dlsch_MCH (eNB, mch_pduP->mcs, 1, 0);
187
    eNB->dlsch_MCH->harq_ids[proc->frame_tx%2][subframe] = 0;
188
    eNB->dlsch_MCH->harq_processes[0]->pdu=(uint8_t *) mch_pduP->payload;
189
    // Generate PMCH
190
    generate_mch (eNB, proc, NULL/*(uint8_t *) mch_pduP->payload*/);
191
  } else {
Raymond Knopp's avatar
Raymond Knopp committed
192
    LOG_D (PHY, "[eNB/RN] Frame %d subframe %d: MCH not generated \n", proc->frame_tx, subframe);
Raymond Knopp's avatar
 
Raymond Knopp committed
193
  }
194
}
195
#endif
196

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
void common_signal_procedures_fembms (PHY_VARS_eNB *eNB,int frame, int subframe) {
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  int **txdataF = eNB->common_vars.txdataF;
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];

  if((frame&3)!=0 /*&& subframe != 0*/)
	  return;

  LOG_I(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s index:%d\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?",(frame&15)/4);
  // generate Cell-Specific Reference Signals for both slots
  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);


  if(subframe_select(fp,subframe) == SF_S)
    generate_pilots_slot(eNB,
                         txdataF,
                         AMP,
                         subframe<<1,1);
  else
    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);

  // First half of PSS/SSS (FDD, slot 0)
  if (subframe == 0) {
    //if (fp->frame_type == FDD) {
      generate_pss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 0);
      generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 5 : 4, 0);
    //}

    /// First half of SSS (TDD, slot 1)

    //if (fp->frame_type == TDD) {
      generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 1);
    //}

    // generate PBCH (Physical Broadcast CHannel) info

    /// generate PBCH
    if ((frame&15)==0) {
      //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n");
      if (eNB->pbch_configured!=1) return;

      eNB->pbch_configured=0;
    }

250 251 252 253 254 255 256 257 258
    if (T_ACTIVE(T_ENB_PHY_MIB)) {
      /* MIB is stored in reverse in pbch_pdu, reverse it for properly logging */
      uint8_t mib[3];
      mib[0] = pbch_pdu[2];
      mib[1] = pbch_pdu[1];
      mib[2] = pbch_pdu[0];
      T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
        T_BUFFER(mib, 3));
    }
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
    generate_pbch_fembms (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, (frame & 15)/4);
  } //else if ((subframe == 1) && (fp->frame_type == TDD)) {
    //generate_pss (txdataF, AMP, fp, 2, 2);
 // }
  // Second half of PSS/SSS (FDD, slot 10)
  else if ((subframe == 5) && (fp->frame_type == FDD) && is_fembms_nonMBSFN_subframe(frame,subframe,fp)) {
     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);
  }
  //  Second-half of SSS (TDD, slot 11)
 // else if ((subframe == 5) && (fp->frame_type == TDD)) {
 //   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)) {
 //   generate_pss (txdataF, AMP, fp, 2, 12);
 // }
}

278
void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
279
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
280
  int **txdataF = eNB->common_vars.txdataF;
281
  uint8_t *pbch_pdu=&eNB->pbch_pdu[0];
282
  //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?");
283
  // generate Cell-Specific Reference Signals for both slots
284
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
285

286
  if(subframe_select(fp,subframe) == SF_S)
287
    generate_pilots_slot(eNB,
frtabu's avatar
frtabu committed
288 289 290
                         txdataF,
                         AMP,
                         subframe<<1,1);
291 292
  else
    generate_pilots_slot(eNB,
frtabu's avatar
frtabu committed
293 294 295
                         txdataF,
                         AMP,
                         subframe<<1,0);
296

297
  // check that 2nd slot is for DL
Raymond Knopp's avatar
Raymond Knopp committed
298 299 300 301 302
  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);

303
  // First half of PSS/SSS (FDD, slot 0)
Raymond Knopp's avatar
 
Raymond Knopp committed
304
  if (subframe == 0) {
305
    if (fp->frame_type == FDD) {
Raymond Knopp's avatar
Raymond Knopp committed
306 307
      generate_pss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 0);
      generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 5 : 4, 0);
308
    }
309

310
    /// First half of SSS (TDD, slot 1)
Raymond Knopp's avatar
Raymond Knopp committed
311

312
    if (fp->frame_type == TDD) {
Raymond Knopp's avatar
Raymond Knopp committed
313
      generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 1);
314
    }
frtabu's avatar
frtabu committed
315

316 317
    // generate PBCH (Physical Broadcast CHannel) info

318
    /// generate PBCH
319
    if ((frame&3)==0) {
320 321
      //AssertFatal(eNB->pbch_configured==1,"PBCH was not configured by MAC\n");
      if (eNB->pbch_configured!=1) return;
frtabu's avatar
frtabu committed
322

323
      eNB->pbch_configured=0;
324
    }
frtabu's avatar
frtabu committed
325

326 327 328 329 330 331 332 333 334
    if (T_ACTIVE(T_ENB_PHY_MIB)) {
      /* MIB is stored in reverse in pbch_pdu, reverse it for properly logging */
      uint8_t mib[3];
      mib[0] = pbch_pdu[2];
      mib[1] = pbch_pdu[1];
      mib[2] = pbch_pdu[0];
      T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
        T_BUFFER(mib, 3));
    }
Raymond Knopp's avatar
Raymond Knopp committed
335 336 337
    generate_pbch (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, frame & 3);
  } else if ((subframe == 1) && (fp->frame_type == TDD)) {
    generate_pss (txdataF, AMP, fp, 2, 2);
338
  }
339
  // Second half of PSS/SSS (FDD, slot 10)
Raymond Knopp's avatar
Raymond Knopp committed
340 341 342
  else if ((subframe == 5) && (fp->frame_type == FDD)) {
    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);
343 344
  }
  //  Second-half of SSS (TDD, slot 11)
Raymond Knopp's avatar
Raymond Knopp committed
345 346
  else if ((subframe == 5) && (fp->frame_type == TDD)) {
    generate_sss (txdataF, AMP, fp, (fp->Ncp == NORMAL) ? 6 : 5, 11);
Raymond Knopp's avatar
 
Raymond Knopp committed
347
  }
348
  // Second half of PSS (TDD, slot 12)
Raymond Knopp's avatar
Raymond Knopp committed
349 350
  else if ((subframe == 6) && (fp->frame_type == TDD)) {
    generate_pss (txdataF, AMP, fp, 2, 12);
351 352
  }
}
Raymond Knopp's avatar
 
Raymond Knopp committed
353

354

355

laurent's avatar
laurent committed
356
bool dlsch_procedures(PHY_VARS_eNB *eNB,
frtabu's avatar
frtabu committed
357 358 359
                      L1_rxtx_proc_t *proc,
                      int harq_pid,
                      LTE_eNB_DLSCH_t *dlsch,
laurent's avatar
laurent committed
360
                      LTE_eNB_UE_stats *ue_stats) {
361 362
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
363
  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
364
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
365

366
  if (dlsch->rnti != 0xffff) {//frame < 200) {
367 368
    LOG_D(PHY,
          "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH (type %d) 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",
frtabu's avatar
frtabu committed
369
          eNB->Mod_id, dlsch->rnti,harq_pid,
370
          frame, subframe, dlsch->ue_type,dlsch_harq->TBS/8, dlsch_harq->pdsch_start,
frtabu's avatar
frtabu committed
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
          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);
  }
388

389
  if (ue_stats) ue_stats->dlsch_sliding_cnt++;
frtabu's avatar
frtabu committed
390

391 392 393
  if (dlsch_harq->round == 0) {
    if (ue_stats)
      ue_stats->dlsch_trials[harq_pid][0]++;
394 395 396 397
  } else {
    ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++;
#ifdef DEBUG_PHY_PROC
#ifdef DEBUG_DLSCH
Raymond Knopp's avatar
Raymond Knopp committed
398
    LOG_D (PHY, "[eNB] This DLSCH is a retransmission\n");
399 400 401
#endif
#endif
  }
402

laurent's avatar
laurent committed
403 404
  if (dlsch->rnti!=0xffff)
    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",
405 406
          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);
Raymond Knopp's avatar
Raymond Knopp committed
407

frtabu's avatar
frtabu committed
408 409 410 411 412
  // 36-212
  if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // 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]);
laurent's avatar
laurent committed
413
      return false;
414
    }
Raymond Knopp's avatar
Raymond Knopp committed
415

416
    start_meas(&eNB->dlsch_encoding_stats);
laurent's avatar
laurent committed
417
    dlsch_encoding_all(eNB,
laurent's avatar
laurent committed
418
		       proc,
frtabu's avatar
frtabu committed
419 420 421 422 423 424 425 426 427 428 429 430
                       dlsch_harq->pdu,
                       dlsch_harq->pdsch_start,
                       dlsch,
                       frame,
                       subframe,
                       &eNB->dlsch_rate_matching_stats,
                       &eNB->dlsch_turbo_encoding_stats,
                       &eNB->dlsch_turbo_encoding_waiting_stats,
                       &eNB->dlsch_turbo_encoding_main_stats,
                       &eNB->dlsch_turbo_encoding_wakeup_stats0,
                       &eNB->dlsch_turbo_encoding_wakeup_stats1,
                       &eNB->dlsch_interleaving_stats);
431
    stop_meas(&eNB->dlsch_encoding_stats);
frtabu's avatar
frtabu committed
432

laurent's avatar
laurent committed
433
    if ( proc->threadPool->activated ) {
laurent's avatar
laurent committed
434 435
    // Wait all other threads finish to process
    while (proc->nbEncode) {
laurent's avatar
laurent committed
436
      delNotifiedFIFO_elt(pullTpool(proc->respEncode, proc->threadPool));
laurent's avatar
laurent committed
437 438 439 440
      proc->nbEncode--;
    }
  }

frtabu's avatar
frtabu committed
441 442 443
    if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1) {
      print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr);
    }
444

Wang Tsu-Han's avatar
Wang Tsu-Han committed
445
#ifdef PHY_TX_THREAD
laurent's avatar
laurent committed
446
    dlsch->active[subframe] = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
447
#else
laurent's avatar
laurent committed
448
    dlsch->active = 0;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
449
#endif
laurent's avatar
laurent committed
450 451 452 453
    dlsch_harq->round++;
    LOG_D(PHY,"Generated DLSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
    return true;
  }
454

laurent's avatar
laurent committed
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
  return false;
}

void pdsch_procedures(PHY_VARS_eNB *eNB,
                      L1_rxtx_proc_t *proc,
                      int harq_pid,
                      LTE_eNB_DLSCH_t *dlsch,
                      LTE_eNB_DLSCH_t *dlsch1) {
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
  LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid];
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  // 36-211
  start_meas(&eNB->dlsch_scrambling_stats);
  dlsch_scrambling(fp,
470 471 472 473 474 475 476 477 478 479 480 481 482 483
                   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);
laurent's avatar
laurent committed
484 485 486
  stop_meas(&eNB->dlsch_scrambling_stats);
  start_meas(&eNB->dlsch_modulation_stats);
  dlsch_modulation(eNB,
487 488 489 490 491 492 493
                   eNB->common_vars.txdataF,
                   AMP,
                   frame,
                   subframe,
                   dlsch_harq->pdsch_start,
                   dlsch,
                   dlsch->ue_type==0 ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL);
laurent's avatar
laurent committed
494 495
  stop_meas(&eNB->dlsch_modulation_stats);
  LOG_D(PHY,"Generated PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round);
496
}
497 498 499



500
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
frtabu's avatar
frtabu committed
501 502
                           L1_rxtx_proc_t *proc,
                           int do_meas) {
503 504
  int frame=proc->frame_tx;
  int subframe=proc->subframe_tx;
505 506
  uint8_t harq_pid;
  uint8_t num_pdcch_symbols=0;
507
  uint8_t num_dci=0;
508
  uint8_t         num_mdci = 0;
509 510
  uint8_t ul_subframe;
  uint32_t ul_frame;
511
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
512
  LTE_UL_eNB_HARQ_t *ulsch_harq;
513

Raymond Knopp's avatar
Raymond Knopp committed
514 515
  if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL))
    return;
516

517
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(eNB->CC_id),1);
frtabu's avatar
frtabu committed
518

519
  if (do_meas==1) start_meas(&eNB->phy_proc_tx);
laurent's avatar
laurent committed
520
  if (do_meas==1) start_meas(&eNB->dlsch_common_and_dci);
521

522
  // clear the transmit data array for the current subframe
523
  for (int aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) {
524 525 526 527 528
    if (eNB->use_DTX==0) 
      memcpy(&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti)],
	     &eNB->subframe_mask[aa][subframe*fp->ofdm_symbol_size*fp->symbols_per_tti],
	     fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t));
    else 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));
Raymond Knopp's avatar
 
Raymond Knopp committed
529
  }
frtabu's avatar
frtabu committed
530 531

  if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
532 533 534 535 536 537 538 539 540 541 542 543 544
    if (is_fembms_pmch_subframe(frame,subframe,fp)) {
#ifdef MBMS_NFAPI_SCHEDULER	    
      pmch_procedures(eNB,proc,1);
      LOG_D(MAC,"frame %d, subframe %d -> PMCH\n",frame,subframe);
      return;
#endif
    }else if(is_fembms_cas_subframe(frame,subframe,fp) || is_fembms_nonMBSFN_subframe(frame,subframe,fp)){
         LOG_D(MAC,"frame %d, subframe %d -> CAS\n",frame,subframe);
	common_signal_procedures_fembms(eNB,proc->frame_tx, proc->subframe_tx);
	//return;
    }

  if((!is_fembms_cas_subframe(frame,subframe,fp)) && (!is_fembms_nonMBSFN_subframe(frame,subframe,fp))){
545
    if (is_pmch_subframe(frame,subframe,fp)) {
546 547 548
#ifdef MBMS_NFAPI_SCHEDULER	    
      pmch_procedures(eNB,proc,0);
#else
549
      pmch_procedures(eNB,proc);
550
#endif
frtabu's avatar
frtabu committed
551
    } else {
552 553 554
      // this is not a pmch subframe, so generate PSS/SSS/PBCH
      common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx);
    }
555
   }
556
  }
frtabu's avatar
frtabu committed
557

Raymond Knopp's avatar
 
Raymond Knopp committed
558
  // clear existing ulsch dci allocations before applying info from MAC  (this is table
Raymond Knopp's avatar
Raymond Knopp committed
559 560
  ul_subframe = pdcch_alloc2ul_subframe (fp, subframe);
  ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe);
frtabu's avatar
frtabu committed
561

Raymond Knopp's avatar
 
Raymond Knopp committed
562
  // clear previous allocation information for all UEs
563
  for (volatile int i = 0; i < NUMBER_OF_DLSCH_MAX; i++) {
564 565 566
    if (eNB->dlsch[i][0])
      eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
  }
frtabu's avatar
frtabu committed
567

568 569 570 571
  /* 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
572
    for (volatile int i=0; i<NUMBER_OF_DLSCH_MAX; i++) {
573
      if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0;
574

frtabu's avatar
frtabu committed
575 576 577
      else
        harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);

578
      if (eNB->ulsch[i]) {
frtabu's avatar
frtabu committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
        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;
600 601 602
      }
    }
  }
frtabu's avatar
frtabu committed
603

604 605
  num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols;
  num_dci           = eNB->pdcch_vars[subframe&1].num_dci;
Cedric Roux's avatar
Cedric Roux committed
606
  LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci);
607
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,num_pdcch_symbols);
Raymond Knopp's avatar
Raymond Knopp committed
608
  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME (VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO, (frame * 10) + subframe);
frtabu's avatar
frtabu committed
609

610
  if (num_pdcch_symbols == 0) {
611 612 613 614
    LOG_E(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);
    return;
  }

615
  if (num_dci > 0)
Cedric Roux's avatar
Cedric Roux committed
616
    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);
frtabu's avatar
frtabu committed
617

618
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
frtabu's avatar
frtabu committed
619 620

  if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
621
    generate_dci_top(num_pdcch_symbols,
frtabu's avatar
frtabu committed
622 623 624 625 626 627 628
                     num_dci,
                     &eNB->pdcch_vars[subframe&1].dci_alloc[0],
                     0,
                     AMP,
                     fp,
                     eNB->common_vars.txdataF,
                     subframe);
629
    num_mdci = eNB->mpdcch_vars[subframe &1].num_dci;
frtabu's avatar
frtabu committed
630

631
    if (num_mdci > 0) {
nepes's avatar
nepes committed
632
      LOG_D (PHY, "[eNB %" PRIu8 "] Frame %d, subframe %d: Calling generate_mdci_top (mpdcch) (num_dci %" PRIu8 ")\n", eNB->Mod_id, frame, subframe, num_mdci);
633
      generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF);
634
    }
635
  }
636

laurent's avatar
laurent committed
637
  if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci);
frtabu's avatar
frtabu committed
638

laurent's avatar
laurent committed
639
  if (do_meas==1) start_meas(&eNB->dlsch_ue_specific);
640

641 642 643 644 645 646 647 648 649 650 651 652
  if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
    if (is_fembms_pmch_subframe(frame,subframe,fp)) {
#ifdef MBMS_NFAPI_SCHEDULER	    
      pmch_procedures(eNB,proc,1);
      return;
#endif
    }else if(is_fembms_cas_subframe(frame,subframe,fp)){
	common_signal_procedures_fembms(eNB,proc->frame_tx, proc->subframe_tx);
    }
  }


653
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
654
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
Raymond Knopp's avatar
 
Raymond Knopp committed
655
  // Now scan UE specific DLSCH
656
  LTE_eNB_DLSCH_t *dlsch0,*dlsch1;
frtabu's avatar
frtabu committed
657

658 659 660
  for (int DLSCH_id=0; DLSCH_id<NUMBER_OF_DLSCH_MAX; DLSCH_id++) {
    dlsch0 = eNB->dlsch[(uint8_t)DLSCH_id][0];
    dlsch1 = eNB->dlsch[(uint8_t)DLSCH_id][1];
frtabu's avatar
frtabu committed
661

662
    if ((dlsch0)&&(dlsch0->rnti>0)&&
Wang Tsu-Han's avatar
Wang Tsu-Han committed
663
#ifdef PHY_TX_THREAD
frtabu's avatar
frtabu committed
664
        (dlsch0->active[subframe] == 1)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
665
#else
frtabu's avatar
frtabu committed
666
        (dlsch0->active == 1)
667
#endif
frtabu's avatar
frtabu committed
668
       ) {
669
      // get harq_pid
670
        harq_pid = dlsch0->harq_ids[frame%2][subframe];
671
      //AssertFatal(harq_pid>=0,"harq_pid is negative\n");
frtabu's avatar
frtabu committed
672

673
      if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
674

frtabu's avatar
frtabu committed
675
        if (dlsch0->ue_type==0)
676
          LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 DLSCH_id:%d frame:%d subframe:%d rnti:%x [ %1d.%1d.%1d.%1d.%1d.%1d.%1d.%1d\n", harq_pid,DLSCH_id,frame,subframe,dlsch0->rnti,
nepes's avatar
nepes committed
677 678 679 680 681 682 683 684
                dlsch0->harq_ids[frame%2][0],
                dlsch0->harq_ids[frame%2][1],
                dlsch0->harq_ids[frame%2][2],
                dlsch0->harq_ids[frame%2][3],
                dlsch0->harq_ids[frame%2][4],
                dlsch0->harq_ids[frame%2][5],
                dlsch0->harq_ids[frame%2][6],
                dlsch0->harq_ids[frame%2][7]);
frtabu's avatar
frtabu committed
685
      } else {
686 687 688 689
        if (dlsch_procedures(eNB,
                             proc,
                             harq_pid,
                             dlsch0,
690
                             &eNB->UE_stats[(uint32_t)DLSCH_id])) {
691 692 693 694 695 696 697
          // if we generate dlsch, we must generate pdsch
          pdsch_procedures(eNB,
                           proc,
                           harq_pid,
                           dlsch0,
                           dlsch1);
        }
nepes's avatar
nepes committed
698
      }
frtabu's avatar
frtabu committed
699
    } else if ((dlsch0)&&(dlsch0->rnti>0)&&
Wang Tsu-Han's avatar
Wang Tsu-Han committed
700
#ifdef PHY_TX_THREAD
frtabu's avatar
frtabu committed
701
               (dlsch0->active[subframe] == 0)
Wang Tsu-Han's avatar
Wang Tsu-Han committed
702
#else
frtabu's avatar
frtabu committed
703
               (dlsch0->active == 0)
704
#endif
frtabu's avatar
frtabu committed
705
              ) {
706
      // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
707
      dlsch0->subframe_tx[subframe]=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
708
    }
frtabu's avatar
frtabu committed
709

710 711
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
  }
frtabu's avatar
frtabu committed
712

713
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,1);
714
  generate_phich_top(eNB,
frtabu's avatar
frtabu committed
715 716
                     proc,
                     AMP);
717
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,0);
718
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(eNB->CC_id),0);
frtabu's avatar
frtabu committed
719

laurent's avatar
laurent committed
720
  if (do_meas==1) stop_meas(&eNB->dlsch_ue_specific);
frtabu's avatar
frtabu committed
721

722
  if (do_meas==1) stop_meas(&eNB->phy_proc_tx);
723 724
}

725
/* This has to be updated with FAPI structures*/
726

727
void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
728
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
Raymond Knopp's avatar
Raymond Knopp committed
729 730 731
  const int       subframe = proc->subframe_rx;
  const int       frame = proc->frame_rx;
  int             i;
frtabu's avatar
frtabu committed
732

Raymond Knopp's avatar
Raymond Knopp committed
733
  if (is_srs_occasion_common (fp, frame, subframe)) {
frtabu's avatar
frtabu committed
734
    // Do SRS processing
Raymond Knopp's avatar
Raymond Knopp committed
735 736
    // check if there is SRS and we have to use shortened format
    // TODO: check for exceptions in transmission of SRS together with ACK/NACK
737
    for (i = 0; i < NUMBER_OF_SRS_MAX; i++) {
Raymond Knopp's avatar
Raymond Knopp committed
738
      if (eNB->soundingrs_ul_config_dedicated[i].active == 1) {
frtabu's avatar
frtabu committed
739 740 741 742 743
        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;
744 745 746 747 748
      }
    }
  }
}

749
void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) {
laurent's avatar
laurent committed
750
  if ( split73 == SPLIT73_DU ) {
laurent's avatar
laurent committed
751
    sendFs6Ulharq(fs6ULindicationSr, UEid, eNB, NULL, frame, subframe, NULL,0,0, rnti, stat);
752 753
    return;
  }
laurent's avatar
laurent committed
754

755
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
756 757 758 759 760 761
  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;
762 763
  pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
764
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
765
  pdu->rx_ue_information.rnti                         = rnti;
Raymond Knopp's avatar
Raymond Knopp committed
766 767
  int SNRtimes10 = dB_fixed_times10(stat) - 10 * eNB->measurements.n0_subband_power_avg_dB;
  LOG_D(PHY,"stat %d subband n0 %d, SNRtimes10 %d\n", stat, eNB->measurements.n0_subband_power_avg_dB, SNRtimes10);
768
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
frtabu's avatar
frtabu committed
769

770 771 772
  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;
frtabu's avatar
frtabu committed
773

774
  pdu->ul_cqi_information.channel = 0;
775
  sr_ind_body->number_of_srs++;
776 777 778
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}

779 780 781 782 783 784 785 786
//-----------------------------------------------------------------------------
/*
 * Main handler of PUCCH received
 */
void
uci_procedures(PHY_VARS_eNB *eNB,
               L1_rxtx_proc_t *proc)
//-----------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
787
{
788 789 790 791 792 793 794
  uint8_t SR_payload = 0;
  uint8_t pucch_b0b1[4][2] = {{0,0},{0,0},{0,0},{0,0}};
  uint8_t harq_ack[4] = {0,0,0,0};
  uint16_t tdd_multiplexing_mask = 0;
  int32_t metric[4] = {0,0,0,0};
  int32_t metric_SR = 0;
  int32_t max_metric = 0;
795 796
  const int subframe = proc->subframe_rx;
  const int frame = proc->frame_rx;
797 798 799
  LTE_eNB_UCI *uci = NULL;
  LTE_DL_FRAME_PARMS *fp = &(eNB->frame_parms);

800
  for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) {
801 802
    uci = &(eNB->uci_vars[i]);

Raymond Knopp's avatar
Raymond Knopp committed
803
    if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) {
804 805 806 807
      if (uci->ue_id > MAX_MOBILES_PER_ENB) {
        LOG_W(PHY, "UCI for UE %d and/or but is not active in MAC\n", uci->ue_id);
        continue;
      }
808 809 810 811 812
      LOG_D(PHY,"Frame %d, subframe %d: Running uci procedures (type %d) for %d \n",
            frame,
            subframe,
            uci->type,
            i);
Raymond Knopp's avatar
Raymond Knopp committed
813
      uci->active = 0;
814

815
      // Null out PUCCH PRBs for noise measurement
Raymond Knopp's avatar
Raymond Knopp committed
816
      switch (fp->N_RB_UL) {
817 818 819
        case 6:
          eNB->rb_mask_ul[0] |= (0x1 | (1 << 5)); // position 5
          break;
820

821 822 823
        case 15:
          eNB->rb_mask_ul[0] |= (0x1 | (1 << 14)); // position 14
          break;
824

825 826 827
        case 25:
          eNB->rb_mask_ul[0] |= (0x1 | (1 << 24)); // position 24
          break;
828

829 830 831 832
        case 50:
          eNB->rb_mask_ul[0] |= 0x1;
          eNB->rb_mask_ul[1] |= (1 << 17); // position 49 (49-32)
          break;
833

834 835 836 837
        case 75:
          eNB->rb_mask_ul[0] |= 0x1;
          eNB->rb_mask_ul[2] |= (1 << 10); // position 74 (74-64)
          break;
838

839 840 841 842
        case 100:
          eNB->rb_mask_ul[0] |= 0x1;
          eNB->rb_mask_ul[3] |= (1 << 3); // position 99 (99-96)
          break;
843

844 845 846
        default:
          LOG_E(PHY,"Unknown number for N_RB_UL %d\n", fp->N_RB_UL);
          break;
847
      }
848

Wang Tsu-Han's avatar
Wang Tsu-Han committed
849
      SR_payload = 0;
850

851
      switch (uci->type) {
frtabu's avatar
frtabu committed
852 853 854 855 856
        case SR:
        case HARQ_SR: {
          int pucch1_thres = (uci->ue_type == 0) ? eNB->pucch1_DTX_threshold : eNB->pucch1_DTX_threshold_emtc[0];
          metric_SR = rx_pucch(eNB,
                               uci->pucch_fmt,
857
                               uci->ue_id,
frtabu's avatar
frtabu committed
858 859 860 861 862 863
                               uci->n_pucch_1_0_sr[0],
                               0, // n2_pucch
                               uci->srs_active, // shortened format
                               &SR_payload,
                               frame,
                               subframe,
864 865
                               pucch1_thres,
                               uci->ue_type
frtabu's avatar
frtabu committed
866 867 868 869 870 871 872 873 874 875 876 877
                              );
          LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR is %d (uci.type %d SR n1pucch is %d)\n",
                eNB->Mod_id,
                uci->rnti,
                frame,
                subframe,
                SR_payload,
                uci->type,
                uci->n_pucch_1_0_sr[0]);

          if (uci->type == SR) {
            if (SR_payload == 1) {
878
              fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR);
frtabu's avatar
frtabu committed
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
              break;
            } else {
              break;
            }
          }
        }

        case HARQ: {
          int pucch1ab_thres = (uci->ue_type == 0) ? eNB->pucch1ab_DTX_threshold : eNB->pucch1ab_DTX_threshold_emtc[0];

          if (fp->frame_type == FDD) {
            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);
            metric[0] = rx_pucch(eNB,
                                 uci->pucch_fmt,
897
                                 uci->ue_id,
frtabu's avatar
frtabu committed
898 899 900 901 902 903
                                 uci->n_pucch_1[0][0],
                                 0, //n2_pucch
                                 uci->srs_active, // shortened format
                                 pucch_b0b1[0],
                                 frame,
                                 subframe,
904 905
                                 pucch1ab_thres,
                                 uci->ue_type
frtabu's avatar
frtabu committed
906 907 908 909 910 911
                                );

            //dump_ulsch(eNB,frame,subframe,0,0); exit(-1);

            /* 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;
912
            else if (SR_payload == 1) fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR);
frtabu's avatar
frtabu committed
913 914 915 916 917 918

            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,
919
                                 uci->ue_id,
frtabu's avatar
frtabu committed
920 921 922 923 924 925
                                 uci->n_pucch_1_0_sr[0],
                                 0, //n2_pucch
                                 uci->srs_active, // shortened format
                                 pucch_b0b1[0],
                                 frame,
                                 subframe,
926 927
                                 pucch1ab_thres,
                                 uci->ue_type
frtabu's avatar
frtabu committed
928 929 930 931 932 933 934 935 936
                                );
            }

            LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d pucch1a (FDD) payload %d (metric %d)\n",
                  eNB->Mod_id,
                  uci->rnti,
                  frame,subframe,
                  pucch_b0b1[0][0],metric[0]);
            uci->stat = metric[0];
937
            fill_uci_harq_indication(i, eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff);
frtabu's avatar
frtabu committed
938 939 940 941 942 943
          } else { // frame_type == TDD
            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);
944
#if 1
frtabu's avatar
frtabu committed
945 946
            metric[0] = rx_pucch(eNB,
                                 uci->pucch_fmt,
947
                                 uci->ue_id,
frtabu's avatar
frtabu committed
948 949 950 951 952 953
                                 uci->n_pucch_1[0][0],
                                 0, //n2_pucch
                                 uci->srs_active, // shortened format
                                 pucch_b0b1[0],
                                 frame,
                                 subframe,
954 955
                                 pucch1ab_thres,
                                 uci->ue_type
frtabu's avatar
frtabu committed
956 957 958
                                );

            if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0;
959
            else if (SR_payload == 1) fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR);
frtabu's avatar
frtabu committed
960 961 962 963 964

            if (uci->type==HARQ_SR && metric[0] <= metric_SR) {
              SR_payload = 1;
              metric[0] = rx_pucch(eNB,
                                   pucch_format1b,
965
                                   uci->ue_id,
frtabu's avatar
frtabu committed
966 967 968 969 970 971
                                   uci->n_pucch_1_0_sr[0],
                                   0, //n2_pucch
                                   uci->srs_active, // shortened format
                                   pucch_b0b1[0],
                                   frame,
                                   subframe,
972 973
                                   pucch1ab_thres,
                                   uci->ue_type
frtabu's avatar
frtabu committed
974 975 976
                                  );
            }

977
#else
frtabu's avatar
frtabu committed
978 979 980

            // if SR was detected, use the n1_pucch from SR
            if (SR_payload==1) {
981
#ifdef DEBUG_PHY_PROC
frtabu's avatar
frtabu committed
982 983
              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);
984
#endif
frtabu's avatar
frtabu committed
985 986 987
              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,
988 989
                                    pucch1ab_thres,
                                    uci->ue_type
frtabu's avatar
frtabu committed
990 991
                                   );
            } else {              //using assigned pucch resources
992
#ifdef DEBUG_PHY_PROC
frtabu's avatar
frtabu committed
993 994 995
              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);
996
#endif
frtabu's avatar
frtabu committed
997 998 999 1000 1001

              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,
1002 1003
                                        pucch1ab_thres,
                                        uci->ue_type
frtabu's avatar
frtabu committed
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
                                       );

              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,
1016 1017
                                       pucch1ab_thres,
                                       uci->ue_type
frtabu's avatar
frtabu committed
1018 1019 1020
                                      );
            }

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1021
#ifdef DEBUG_PHY_PROC
frtabu's avatar
frtabu committed
1022 1023
            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",
                  uci->rnti,uci->type,SR_payload,frame,subframe,pucch_b0b1[0][0],pucch_b0b1[0][1],pucch_b0b1[1][0],pucch_b0b1[1][1]);
sharma's avatar
sharma committed
1024
#endif
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1025
#endif
1026

frtabu's avatar
frtabu committed
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
            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
              } else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1) { // 1/4/7 ACKs
                harq_ack[0] = 1;
              } else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] != 1) { // 2/5/8 ACKs
                harq_ack[0] = 2;
              } else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] == 1) { // 3/6/9 ACKs
                harq_ack[0] = 3;
              } else if (pucch_b0b1[0][0] != 1 && pucch_b0b1[0][1] != 1) { // 0 ACKs, or at least one DL assignment missed
                harq_ack[0] = 0;
              }

              uci->stat = metric[0];
1041
              fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode
frtabu's avatar
frtabu committed
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
            } 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
              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
                  }
                }
              }

              uci->stat = max(metric[0],metric[1]);
1077
              fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
frtabu's avatar
frtabu committed
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
            } //else if ((uci->tdd_bundling == 0) && (res==2))
            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
              if (harq_ack[0] == 4 ||
                  harq_ack[1] == 4 ||
                  harq_ack[2] == 4) { // there isn't a likely transmission
                harq_ack[0] = 4; // DTX
                harq_ack[1] = 6; // NACK/DTX
                harq_ack[2] = 6; // NACK/DTX
                max_metric = 0;
              } else {
                max_metric = max(metric[0],max(metric[1],metric[2]));

                if (metric[0]==max_metric) {
                  if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 6; // NACK/DTX
                    harq_ack[2] = 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
                    harq_ack[2] = 6; // NACK/DTX
                  } else {
                    harq_ack[0] = 4; // DTX
                    harq_ack[1] = 4; // DTX
                    harq_ack[2] = 4; // DTX
                  }
                } // if (metric[0]==max_metric) {
                else if (metric[1]==max_metric) {
                  if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] != 1) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 6; // NACK/DTX
                    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
                    harq_ack[2] = 6; // NACK/DTX
                    tdd_multiplexing_mask = 0x2;
                  } else {
                    harq_ack[0] = 4; // DTX
                    harq_ack[1] = 4; // DTX
                    harq_ack[2] = 4; // DTX
                  }
                } // if (metric[1]==max_metric) {
                else {
                  if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] == 1) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 1; // ACK
                    tdd_multiplexing_mask = 0x7;
                  } else if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] != 1 ) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 6; // NACK/DTX
                    harq_ack[2] = 1; // ACK
                    tdd_multiplexing_mask = 0x5;
                  } else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] == 1 ) {
                    harq_ack[0] = 6; // NACK/DTX
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 1; // ACK
                    tdd_multiplexing_mask = 0x6;
                  } else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] != 1 ) {
                    harq_ack[0] = 6; // NACK/DTX
                    harq_ack[1] = 6; // NACK/DTX
                    harq_ack[2] = 1; // ACK
                    tdd_multiplexing_mask = 0x4;
                  }
                }

                uci->stat = max_metric;
1148
                fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
frtabu's avatar
frtabu committed
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
              }
            } //else if ((uci->tdd_bundling == 0) && (res==3))
            else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==4)) { // multiplexing + no SR, implement Table 10.1.3-7 (Rel14) for multiplexing with M=4
              if (pucch_b0b1[0][0] == 4 ||
                  pucch_b0b1[1][0] == 4 ||
                  pucch_b0b1[2][0] == 4 ||
                  pucch_b0b1[3][0] == 4) { // there isn't a likely transmission
                harq_ack[0] = 4; // DTX
                harq_ack[1] = 6; // NACK/DTX
                harq_ack[2] = 6; // NACK/DTX
                harq_ack[3] = 6; // NACK/DTX
                max_metric = 0;
              } else {
                max_metric = max(metric[0],max(metric[1],max(metric[2],metric[3])));

                if (metric[0]==max_metric) {
                  if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] != 1) {
                    harq_ack[0] = 2; // NACK
                    harq_ack[1] = 4; // DTX
                    harq_ack[2] = 4; // DTX
                    harq_ack[3] = 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
                    harq_ack[2] = 6; // NACK/DTX
                    harq_ack[3] = 1; // ACK
                    tdd_multiplexing_mask = 0x9;
                  } else if (pucch_b0b1[0][0] == 1 && pucch_b0b1[0][1] == 1) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 6; // NACK/DTX
                    harq_ack[2] = 6; // NACK/DTX
                    harq_ack[3] = 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
                    harq_ack[2] = 6; // NACK/DTX
                    harq_ack[3] = 6; // NACK/DTX
                  }
                } else if (metric[1]==max_metric) {
                  if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] == 1) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 1; // ACK
                    harq_ack[3] = 1; // ACK
                    tdd_multiplexing_mask = 0xF;
                  } else if (pucch_b0b1[1][0] == 1 && pucch_b0b1[1][1] != 1 ) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 6; // NACK/DTX
                    harq_ack[3] = 6; // NACK/DTX
                    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
                    harq_ack[2] = 1; // ACK
                    harq_ack[3] = 1; // ACK
                    tdd_multiplexing_mask = 0xE;
                  } else if (pucch_b0b1[1][0] != 1 && pucch_b0b1[1][1] == 1 ) {
                    harq_ack[0] = 6; // NACK/DTX
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 6; // NACK/DTX
                    harq_ack[3] = 6; // NACK/DTX
                    tdd_multiplexing_mask = 0x2;
                  }
                } else if (metric[2]==max_metric) {
                  if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] == 1) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 1; // ACK
                    harq_ack[3] = 6; // NACK/DTX
                    tdd_multiplexing_mask = 0x7;
                  } else if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] != 1 ) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 6; // NACK/DTX
                    harq_ack[2] = 1; // ACK
                    harq_ack[3] = 6; // NACK/DTX
                    tdd_multiplexing_mask = 0x5;
                  } else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] == 1 ) {
                    harq_ack[0] = 4; // NACK/DTX
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 1; // ACK
                    harq_ack[3] = 4; // NACK/DTX
                    tdd_multiplexing_mask = 0x6;
                  } else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] != 1 ) {
                    harq_ack[0] = 4; // NACK/DTX
                    harq_ack[1] = 4; // NACK/DTX
                    harq_ack[2] = 1; // ACK
                    harq_ack[3] = 4; // NACK/DTX
                    tdd_multiplexing_mask = 0x4;
                  }
                } else { // max_metric[3]=max_metric
                  if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] == 1) {
                    harq_ack[0] = 1; // ACK
                    harq_ack[1] = 6; // NACK/DTX
                    harq_ack[2] = 1; // ACK
                    harq_ack[3] = 1; // ACK
                    tdd_multiplexing_mask = 0xD;
                  } else if (pucch_b0b1[2][0] == 1 && pucch_b0b1[2][1] != 1 ) {
                    harq_ack[0] = 6; // NACK/DTX
                    harq_ack[1] = 1; // ACK
                    harq_ack[2] = 6; // NACK/DTX
                    harq_ack[3] = 1; // ACK
                    tdd_multiplexing_mask = 0xA;
                  } else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] == 1 ) {
                    harq_ack[0] = 6; // NACK/DTX
                    harq_ack[1] = 6; // NACK/DTX
                    harq_ack[2] = 1; // ACK
                    harq_ack[3] = 1; // ACK
                    tdd_multiplexing_mask = 0xC;
                  } else if (pucch_b0b1[2][0] != 1 && pucch_b0b1[2][1] != 1 ) {
                    harq_ack[0] = 6; // NACK/DTX
                    harq_ack[1] = 6; // NACK/DTX
                    harq_ack[2] = 6; // NACK/DTX
                    harq_ack[3] = 1; // ACK
                    tdd_multiplexing_mask = 0x8;
                  }
                }
              }

              uci->stat = max_metric;
1270
              fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode
frtabu's avatar
frtabu committed
1271 1272 1273 1274 1275 1276
            } // else if ((uci->tdd_bundling == 0) && (res==4))
            else { // bundling
              harq_ack[0] = pucch_b0b1[0][0];
              harq_ack[1] = pucch_b0b1[0][1];
              uci->stat = metric[0];
              LOG_D(PHY,"bundling: (%d,%d), metric %d\n",harq_ack[0],harq_ack[1],uci->stat);
1277
              fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode
frtabu's avatar
frtabu committed
1278 1279
            }

1280
#ifdef DEBUG_PHY_PROC
frtabu's avatar
frtabu committed
1281
            LOG_D (PHY, "[eNB %d][PDSCH %x] Frame %d subframe %d ACK/NAK metric 0 %d, metric 1 %d, (%d,%d)\n", eNB->Mod_id,
1282
                   eNB->dlsch[DLSCH_id][0]->rnti, frame, subframe, metric0, metric1, pucch_b0b1[0], pucch_b0b1[1]);
1283
#endif
frtabu's avatar
frtabu committed
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
          }

          break;

          default:
            AssertFatal (1 == 0, "Unsupported UCI type %d\n", uci->type);
            break;
          }

          if (SR_payload == 1) {
            LOG_D (PHY, "[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n", eNB->Mod_id, uci->rnti, frame, subframe);

1296 1297 1298 1299 1300
            if (eNB->first_sr[uci->ue_id] == 1) {    // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4
              eNB->first_sr[uci->ue_id] = 0;
              eNB->dlsch[uci->ue_id][0]->harq_processes[0]->round = 0;
              eNB->dlsch[uci->ue_id][0]->harq_processes[0]->status = SCH_IDLE;
              LOG_D (PHY, "[eNB %d][SR %x] Frame %d subframe %d First SR\n", eNB->Mod_id, eNB->ulsch[uci->ue_id]->rnti, frame, subframe);
frtabu's avatar
frtabu committed
1301 1302
            }
          }
Cedric Roux's avatar
Cedric Roux committed
1303
      }
1304
    } // end if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) {
1305
  } // end loop for (int i = 0; i < NUMBER_OF_UCI_MAX; i++) {
1306
}
1307

1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) {
  turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req);

  LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid];
  LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
  PHY_VARS_eNB *eNB=rdata->eNB;
    
  bool decodeSucess=rdata->decodeIterations <= rdata->maxIterations;
  ulsch_harq->processedSegments++;
  LOG_D(PHY, "processing result of segment: %d, ue %d, processed %d/%d\n",
	rdata->segment_r, rdata->UEid, ulsch_harq->processedSegments, rdata->nbSegments);
  proc->nbDecode--;
  LOG_D(PHY,"remain to decoded in subframe: %d\n", proc->nbDecode);
  if (decodeSucess)  {
    int Fbytes=(rdata->segment_r==0) ? rdata->Fbits>>3 : 0;
    int sz=(rdata->Kr>>3) - Fbytes - ((ulsch_harq->C>1)?3:0);
laurent's avatar
laurent committed
1324
    memcpy(ulsch_harq->decodedBytes+rdata->offset,
1325 1326 1327 1328
	   rdata->decoded_bytes+Fbytes,
	   sz);
  } else {
    if ( rdata->nbSegments != ulsch_harq->processedSegments ) {
laurent's avatar
laurent committed
1329 1330
      int nb=abortTpool(proc->threadPool, req->key);
      nb+=abortNotifiedFIFO(proc->respDecode, req->key);
1331
      proc->nbDecode-=nb;
1332
      LOG_D(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb);
1333 1334 1335
      AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n",
		  ulsch_harq->processedSegments, nb, rdata->nbSegments);
      ulsch_harq->processedSegments=rdata->nbSegments;
laurent's avatar
laurent committed
1336
    }
1337
  }
laurent's avatar
laurent committed
1338

1339 1340 1341 1342 1343 1344 1345 1346
  // if this UE segments are all done
  if ( rdata->nbSegments == ulsch_harq->processedSegments) {
      //compute the expected ULSCH RX power (for the stats)
      int i=rdata->UEid;
      ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,rdata->harq_pid, 0); // 0 means bw_factor is not considered
      if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */
	if (ulsch_harq->cqi_crc_status == 1) {
	  fill_ulsch_cqi_indication(eNB,rdata->frame,rdata->subframe,ulsch_harq,ulsch->rnti);
laurent's avatar
laurent committed
1347
	  RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << rdata->subframe));
1348
	} else {
laurent's avatar
laurent committed
1349 1350 1351
	  if(RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag & (1 << rdata->subframe) ) {
	    RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << rdata->subframe));
	    RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_timer=30;
1352 1353 1354 1355 1356 1357
	    LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",rdata->frame,rdata->subframe);
	  }
	}
      }
	
      if (!decodeSucess) {
1358 1359
        T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(rdata->frame), T_INT(rdata->subframe), T_INT(ulsch->rnti),
          T_INT(rdata->harq_pid));
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
	fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,1); // indicate NAK to MAC
	fill_rx_indication(eNB,i,rdata->frame,rdata->subframe);  // indicate SDU to MAC
	LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n",
	      eNB->Mod_id,rdata->harq_pid,
	      rdata->frame,rdata->subframe, i,
	      ulsch_harq->round,
	      ulsch->Mlimit,
	      ulsch_harq->o_ACK[0],
	      ulsch_harq->o_ACK[1]);
	  
	if (ulsch_harq->round >= 3)  {
	  ulsch_harq->status  = SCH_IDLE;
	  ulsch_harq->handled = 0;
	  ulsch->harq_mask   &= ~(1 << rdata->harq_pid);
	  ulsch_harq->round   = 0;
	}
	/* Mark the HARQ process to release it later if max transmission reached
	 * (see below).
	 * MAC does not send the max transmission count, we have to deal with it
	 * locally in PHY.
	 */
	ulsch_harq->handled = 1;
      }  // ulsch in error
      else if(ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions){
	fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,0); // indicate ACK to MAC
	fill_rx_indication(eNB,i,rdata->frame,rdata->subframe);  // indicate SDU to MAC
	ulsch_harq->status = SCH_IDLE;
	ulsch->harq_mask &= ~(1 << rdata->harq_pid);
1388 1389 1390 1391 1392 1393 1394 1395 1396
	for (int j=0;j<NUMBER_OF_ULSCH_MAX;j++) 
           if (eNB->ulsch_stats[j].rnti == ulsch->rnti) {
              eNB->ulsch_stats[j].total_bytes_rx+=ulsch_harq->TBS;
              for (int aa=0;aa<eNB->frame_parms.nb_antennas_rx;aa++) {
                eNB->ulsch_stats[j].ulsch_power[aa] = dB_fixed_times10(eNB->pusch_vars[rdata->UEid]->ulsch_power[aa]);
                eNB->ulsch_stats[j].ulsch_noise_power[aa] = dB_fixed_times10(eNB->pusch_vars[rdata->UEid]->ulsch_noise_power[aa]); 
              }
              break;
           }
1397 1398
        T (T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(rdata->frame), T_INT(rdata->subframe), T_INT(ulsch->rnti),
           T_INT(rdata->harq_pid));
1399 1400 1401 1402 1403
      }  // ulsch not in error
	
      if (ulsch_harq->O_ACK>0)
	fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,rdata->frame,rdata->subframe,ulsch->bundling);
  } 
laurent's avatar
laurent committed
1404 1405
}

frtabu's avatar
frtabu committed
1406
void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
1407
  uint32_t i;
Raymond Knopp's avatar
Raymond Knopp committed
1408
  uint32_t harq_pid;
1409 1410 1411 1412 1413 1414
  uint8_t nPRS;
  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
  LTE_eNB_ULSCH_t *ulsch;
  LTE_UL_eNB_HARQ_t *ulsch_harq;
  const int subframe = proc->subframe_rx;
  const int frame    = proc->frame_rx;
nepes's avatar
nepes committed
1415
  uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe);
1416

1417
  for (i = 0; i < NUMBER_OF_ULSCH_MAX; i++) {
1418
    ulsch = eNB->ulsch[i];
frtabu's avatar
frtabu committed
1419 1420 1421 1422

    if (ulsch->ue_type > 0) harq_pid = 0;
    else harq_pid=harq_pid0;

1423
    ulsch_harq = ulsch->harq_processes[harq_pid];
frtabu's avatar
frtabu committed
1424

1425
    if (ulsch->rnti>0) LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n",
frtabu's avatar
frtabu committed
1426 1427 1428
                               i, harq_pid, frame,subframe,i,ulsch->rnti,
                               ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled);

1429
    if ((ulsch) &&
frtabu's avatar
frtabu committed
1430 1431
        (ulsch->rnti>0) &&
        (ulsch_harq->status == ACTIVE) &&
1432 1433
        ((ulsch_harq->frame == frame)	    || (ulsch_harq->repetition_number >1) ) &&
        ((ulsch_harq->subframe == subframe) || (ulsch_harq->repetition_number >1) ) &&
frtabu's avatar
frtabu committed
1434
        (ulsch_harq->handled == 0)) {
1435
      // UE has ULSCH scheduling
1436
      for (int rb=0;
frtabu's avatar
frtabu committed
1437 1438 1439 1440
           rb<=ulsch_harq->nb_rb;
           rb++) {
        int rb2 = rb+ulsch_harq->first_rb;
        eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
1441
      }
frtabu's avatar
frtabu committed
1442

Cedric Roux's avatar
Cedric Roux committed
1443
      LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", eNB->Mod_id, frame, subframe, i);
1444
      nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
Cedric Roux's avatar
Cedric Roux committed
1445
      ulsch->cyclicShift = (ulsch_harq->n_DMRS2 +
frtabu's avatar
frtabu committed
1446 1447 1448
                            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +
                            nPRS)%12;
      AssertFatal(ulsch_harq->TBS>0,"illegal TBS %d\n",ulsch_harq->TBS);
1449
      LOG_D(PHY,
frtabu's avatar
frtabu committed
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464
            "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, Qm %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, ), O_ACK %d, beta_cqi %d \n",
            eNB->Mod_id,harq_pid,frame,subframe,
            ulsch_harq->dci_alloc,
            ulsch_harq->rar_alloc,
            ulsch_harq->round,
            ulsch_harq->first_rb,
            ulsch_harq->nb_rb,
            ulsch_harq->Qm,
            ulsch_harq->TBS,
            ulsch_harq->rvidx,
            ulsch->cyclicShift,
            ulsch_harq->n_DMRS2,
            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
            ulsch_harq->O_ACK,
            ulsch->beta_offset_cqi_times8);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1465 1466 1467 1468
      start_meas(&eNB->ulsch_demodulation_stats);
      rx_ulsch(eNB,proc, i);
      stop_meas(&eNB->ulsch_demodulation_stats);
      start_meas(&eNB->ulsch_decoding_stats);
1469
      ulsch_decoding(eNB,proc,
frtabu's avatar
frtabu committed
1470 1471 1472 1473
                           i,
                           0, // control_only_flag
                           ulsch_harq->V_UL_DAI,
                           ulsch_harq->nb_rb>20 ? 1 : 0);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1474
      stop_meas(&eNB->ulsch_decoding_stats);
Raymond Knopp's avatar
Raymond Knopp committed
1475
/*
1476 1477 1478 1479 1480 1481 1482 1483 1484
      int ulsch_id=-1;
      for  (ulsch_id=0;ulsch_id<NUMBER_OF_ULSCH_MAX;ulsch_id++)
         if (ulsch->rnti == eNB->ulsch_stats[ulsch_id].rnti) break;
      AssertFatal(ulsch_id>=0,"no ulsch_id found\n");

      if (eNB->ulsch_stats[ulsch_id].round_trials[0]>100) {
         dump_ulsch(eNB,frame,subframe,i,ulsch_harq->round);
         AssertFatal(1==0,"exiting\n");
      }
Raymond Knopp's avatar
Raymond Knopp committed
1485
*/
1486
    }
1487
    else if ((ulsch) &&
frtabu's avatar
frtabu committed
1488 1489 1490 1491 1492
             (ulsch->rnti>0) &&
             (ulsch_harq->status == ACTIVE) &&
             (ulsch_harq->frame == frame) &&
             (ulsch_harq->subframe == subframe) &&
             (ulsch_harq->handled == 1)) {
Cedric Roux's avatar
Cedric Roux committed
1493 1494 1495
      // this harq process is stale, kill it, this 1024 frames later (10s), consider reducing that
      ulsch_harq->status = SCH_IDLE;
      ulsch_harq->handled = 0;
Raymond Knopp's avatar
Raymond Knopp committed
1496 1497
      ulsch->harq_mask &= ~(1 << harq_pid);
      LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask);
1498
    }
1499
  }   //   for (i=0; i<NUMBER_OF_ULSCH_MAX; i++)
1500 1501
  
  while (proc->nbDecode > 0) {
laurent's avatar
laurent committed
1502
    notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool);
1503 1504 1505
    postDecode(proc, req);
    delNotifiedFIFO_elt(req);
  }
1506
}
1507

1508
extern int      oai_exit;
1509

Raymond Knopp's avatar
Raymond Knopp committed
1510
extern void    *td_thread (void *);
1511

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1512
void init_td_thread(PHY_VARS_eNB *eNB) {
1513
	/*
1514
  L1_proc_t *proc = &eNB->proc;
1515
  proc->tdp.eNB = eNB;
1516
  proc->instance_cnt_td = -1;
1517
  threadCreate(&proc->pthread_td, td_thread, (void *)&proc->tdp, "TD", -1, OAI_PRIORITY_RT);
1518
  */
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1519
}
1520

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1521
void kill_td_thread(PHY_VARS_eNB *eNB) {
1522
	/*
1523
  L1_proc_t *proc = &eNB->proc;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1524 1525 1526 1527 1528
  proc->instance_cnt_td         = 0;
  pthread_cond_signal(&proc->cond_td);
  pthread_join(proc->pthread_td, NULL);
  pthread_mutex_destroy( &proc->mutex_td );
  pthread_cond_destroy( &proc->cond_td );
1529
  */
1530 1531
}

Raymond Knopp's avatar
Raymond Knopp committed
1532
extern void    *te_thread (void *);
1533

1534
void init_te_thread(PHY_VARS_eNB *eNB) {
1535
	/*
1536
  L1_proc_t *proc = &eNB->proc;
1537

frtabu's avatar
frtabu committed
1538
  for(int i=0; i<3 ; i++) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1539
    proc->tep[i].eNB = eNB;
1540
    proc->tep[i].instance_cnt_te = -1;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1541
    LOG_I(PHY,"Creating te_thread %d\n",i);
Laurent's avatar
Laurent committed
1542
    char txt[128];
1543 1544
    sprintf(txt,"TE_%d", i);
    threadCreate(&proc->tep[i].pthread_te, te_thread, (void *)&proc->tep[i], txt, -1, OAI_PRIORITY_RT);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1545
  }
1546
  */
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1547
}
1548

1549
void kill_te_thread(PHY_VARS_eNB *eNB) {
1550
	/*
1551
  L1_proc_t *proc = &eNB->proc;
1552

frtabu's avatar
frtabu committed
1553
  for(int i=0; i<3 ; i++) {
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1554 1555 1556
    proc->tep[i].instance_cnt_te         = 0;
    pthread_cond_signal(&proc->tep[i].cond_te);
    pthread_join(proc->tep[i].pthread_te, NULL);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1557 1558
    pthread_mutex_destroy( &proc->tep[i].mutex_te);
    pthread_cond_destroy( &proc->tep[i].cond_te);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1559
  }
1560
  */
1561 1562
}

1563
void fill_rx_indication(PHY_VARS_eNB *eNB,
1564
                        int ULSCH_id,
1565 1566
                        int frame,
                        int subframe) {
1567
  nfapi_rx_indication_pdu_t *pdu;
Raymond Knopp's avatar
Raymond Knopp committed
1568 1569
  int             timing_advance_update;
  int             sync_pos;
1570
  uint32_t        harq_pid;
frtabu's avatar
frtabu committed
1571

1572
  if (eNB->ulsch[ULSCH_id]->ue_type > 0) harq_pid = 0;
1573
  else {
frtabu's avatar
frtabu committed
1574 1575 1576 1577
    harq_pid = subframe2harq_pid (&eNB->frame_parms,
                                  frame, subframe);
  }

1578
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
1579 1580 1581
  eNB->UL_INFO.rx_ind.sfn_sf                    = frame<<4| subframe;
  eNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG;
  pdu                                    = &eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus];
1582
  //  pdu->rx_ue_information.handle          = eNB->ulsch[ULSCH_id]->handle;
1583
  pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
1584
  pdu->rx_ue_information.rnti            = eNB->ulsch[ULSCH_id]->rnti;
1585
  pdu->rx_indication_rel8.tl.tag         = NFAPI_RX_INDICATION_REL8_TAG;
1586
  pdu->rx_indication_rel8.length         = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->TBS>>3;
1587
  pdu->rx_indication_rel8.offset         = 1;   // DJP - I dont understand - but broken unless 1 ????  0;  // filled in at the end of the UL_INFO formation
1588
  pdu->data                              = eNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->decodedBytes;
1589
  // estimate timing advance for MAC
1590 1591 1592 1593 1594 1595 1596 1597
  sync_pos                               = lte_est_timing_advance_pusch(&eNB->frame_parms, eNB->pusch_vars[ULSCH_id]->drs_ch_estimates_time);
  timing_advance_update                  = sync_pos; 

  for (int i=0;i<NUMBER_OF_SCH_STATS_MAX;i++) 
      if (eNB->ulsch_stats[i].rnti == eNB->ulsch[ULSCH_id]->rnti) 
         eNB->ulsch_stats[i].timing_offset = sync_pos;
  //  if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,ULSCH_id); exit(-1);}
  //  if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,ULSCH_id); exit(-1);}
1598
  switch (eNB->frame_parms.N_RB_DL) {
frtabu's avatar
frtabu committed
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623
    case 6:                      /* nothing to do */
      break;

    case 15:
      timing_advance_update /= 2;
      break;

    case 25:
      timing_advance_update /= 4;
      break;

    case 50:
      timing_advance_update /= 8;
      break;

    case 75:
      timing_advance_update /= 12;
      break;

    case 100:
      timing_advance_update /= 16;
      break;

    default:
      abort ();
1624
  }
frtabu's avatar
frtabu committed
1625

1626
  // put timing advance command in 0..63 range
Cedric Roux's avatar
Cedric Roux committed
1627
  timing_advance_update += 31;
frtabu's avatar
frtabu committed
1628

Raymond Knopp's avatar
Raymond Knopp committed
1629 1630
  if (timing_advance_update < 0)
    timing_advance_update = 0;
frtabu's avatar
frtabu committed
1631

Raymond Knopp's avatar
Raymond Knopp committed
1632 1633
  if (timing_advance_update > 63)
    timing_advance_update = 63;
frtabu's avatar
frtabu committed
1634

Cedric Roux's avatar
Cedric Roux committed
1635
  pdu->rx_indication_rel8.timing_advance = timing_advance_update;
Raymond Knopp's avatar
Raymond Knopp committed
1636
  // estimate UL_CQI for MAC 
1637 1638 1639 1640 1641 1642 1643
  int total_power=0, avg_noise_power=0;  
  for (int i=0;i<eNB->frame_parms.nb_antennas_rx;i++) {
     total_power+=(eNB->pusch_vars[ULSCH_id]->ulsch_power[i]);
     avg_noise_power+=(eNB->pusch_vars[ULSCH_id]->ulsch_noise_power[i])/eNB->frame_parms.nb_antennas_rx;
  }
  int SNRtimes10 = dB_fixed_times10(total_power) - 
                   dB_fixed_times10(avg_noise_power);
1644

Raymond Knopp's avatar
Raymond Knopp committed
1645 1646 1647 1648 1649 1650
  if (SNRtimes10 < -640)
    pdu->rx_indication_rel8.ul_cqi = 0;
  else if (SNRtimes10 > 635)
    pdu->rx_indication_rel8.ul_cqi = 255;
  else
    pdu->rx_indication_rel8.ul_cqi = (640 + SNRtimes10) / 5;
frtabu's avatar
frtabu committed
1651

Raymond Knopp's avatar
Raymond Knopp committed
1652
  LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d,%d,%d), timing_advance %d (update %d,sync_pos %d)\n",
1653 1654
        harq_pid,frame,subframe,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,dB_fixed_times10(total_power),dB_fixed_times10(avg_noise_power),pdu->rx_indication_rel8.timing_advance,timing_advance_update,sync_pos);
  for (int i=0;i<eNB->frame_parms.nb_antennas_rx;i++)
Raymond Knopp's avatar
Raymond Knopp committed
1655
	LOG_D(PHY,"antenna %d: ulsch_power %d, noise_power %d\n",i,dB_fixed_times10(eNB->pusch_vars[ULSCH_id]->ulsch_power[i]),dB_fixed_times10(eNB->pusch_vars[ULSCH_id]->ulsch_noise_power[i]));
1656

1657 1658
  eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++;
  eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe;
1659 1660
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}
1661

1662 1663
//-----------------------------------------------------------------------------
/*
1664
 * Release the harq process if its round is >= 'after_rounds'
1665 1666
 */
static void do_release_harq(PHY_VARS_eNB *eNB,
1667
                            int DLSCH_id,
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678
                            int tb,
                            uint16_t frame,
                            uint8_t subframe,
                            uint16_t mask,
                            int after_rounds)
//-----------------------------------------------------------------------------
{
  LTE_eNB_DLSCH_t *dlsch0 = NULL;
  LTE_eNB_DLSCH_t *dlsch1 = NULL;
  LTE_DL_eNB_HARQ_t *dlsch0_harq = NULL;
  LTE_DL_eNB_HARQ_t *dlsch1_harq = NULL;
1679
  int harq_pid;
1680 1681
  int subframe_tx;
  int frame_tx;
1682 1683 1684 1685
  AssertFatal(DLSCH_id != -1, "No existing dlsch context\n");
  AssertFatal(DLSCH_id < NUMBER_OF_DLSCH_MAX, "Returned DLSCH_id %d >= %d (NUMBER_OF_DLSCH_MAX)\n", DLSCH_id, NUMBER_OF_DLSCH_MAX);
  dlsch0 = eNB->dlsch[DLSCH_id][0];
  dlsch1 = eNB->dlsch[DLSCH_id][1];
1686 1687 1688 1689

  if (eNB->frame_parms.frame_type == FDD) {
    subframe_tx = (subframe + 6) % 10;
    frame_tx = ul_ACK_subframe2_dl_frame(&eNB->frame_parms,
1690 1691 1692
                                         frame,
                                         subframe,
                                         subframe_tx);
1693 1694
    harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];

1695 1696 1697 1698
    if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
      LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
      return;
    }
1699

1700 1701 1702
    dlsch0_harq = dlsch0->harq_processes[harq_pid];
    dlsch1_harq = dlsch1->harq_processes[harq_pid];
    AssertFatal(dlsch0_harq != NULL, "dlsch0_harq is null\n");
Cedric Roux's avatar
Cedric Roux committed
1703
#if T_TRACER
frtabu's avatar
frtabu committed
1704

Cedric Roux's avatar
Cedric Roux committed
1705
    if (after_rounds != -1) {
1706 1707 1708 1709 1710 1711
      T(T_ENB_PHY_DLSCH_UE_NACK,
        T_INT(0),
        T_INT(frame),
        T_INT(subframe),
        T_INT(dlsch0->rnti),
        T_INT(harq_pid));
Cedric Roux's avatar
Cedric Roux committed
1712
    } else {
1713 1714 1715 1716 1717 1718
      T(T_ENB_PHY_DLSCH_UE_ACK,
        T_INT(0),
        T_INT(frame),
        T_INT(subframe),
        T_INT(dlsch0->rnti),
        T_INT(harq_pid));
Cedric Roux's avatar
Cedric Roux committed
1719
    }
frtabu's avatar
frtabu committed
1720

Cedric Roux's avatar
Cedric Roux committed
1721
#endif
1722

1723 1724
    if (dlsch0_harq->round >= after_rounds) {
      dlsch0_harq->status = SCH_IDLE;
1725
      dlsch0->harq_mask &= ~(1 << harq_pid);
1726
    }
1727 1728 1729 1730 1731 1732
  } else {
    /* Release all processes in the bundle that was acked, based on mask */
    /* This is at most 4 for multiplexing and 9 for bundling/special bundling */
    int M = ul_ACK_subframe2_M(&eNB->frame_parms, subframe);

    for (int m=0; m < M; m++) {
1733
      subframe_tx = ul_ACK_subframe2_dl_subframe(&eNB->frame_parms,
1734 1735
                    subframe,
                    m);
1736
      frame_tx = ul_ACK_subframe2_dl_frame(&eNB->frame_parms,
1737 1738 1739
                                           frame,
                                           subframe,
                                           subframe_tx);
1740 1741 1742 1743

      if (((1 << m) & mask) > 0) {
        harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];

1744 1745 1746 1747
        if((harq_pid < 0) || (harq_pid >= dlsch0->Mdlharq)) {
          LOG_E(PHY,"illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__);
          return;
        }
1748

Haruki NAOI's avatar
Haruki NAOI committed
1749 1750 1751
        dlsch0_harq = dlsch0->harq_processes[harq_pid];
        dlsch1_harq = dlsch1->harq_processes[harq_pid];
        AssertFatal(dlsch0_harq != NULL, "Dlsch0_harq is null\n");
Cedric Roux's avatar
Cedric Roux committed
1752
#if T_TRACER
1753

Haruki NAOI's avatar
Haruki NAOI committed
1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768
        if (after_rounds != -1) {
          T(T_ENB_PHY_DLSCH_UE_NACK,
            T_INT(0),
            T_INT(frame),
            T_INT(subframe),
            T_INT(dlsch0->rnti),
            T_INT(harq_pid));
        } else {
          T(T_ENB_PHY_DLSCH_UE_ACK,
            T_INT(0),
            T_INT(frame),
            T_INT(subframe),
            T_INT(dlsch0->rnti),
            T_INT(harq_pid));
        }
1769

Cedric Roux's avatar
Cedric Roux committed
1770
#endif
1771

Haruki NAOI's avatar
Haruki NAOI committed
1772 1773
        if (dlsch0_harq->round >= after_rounds) {
          dlsch0_harq->status = SCH_IDLE;
1774

Haruki NAOI's avatar
Haruki NAOI committed
1775 1776
          if ((dlsch1_harq == NULL) || ((dlsch1_harq != NULL) && (dlsch1_harq->status == SCH_IDLE))) {
            dlsch0->harq_mask &= ~(1 << harq_pid);
1777
          }
Haruki NAOI's avatar
Haruki NAOI committed
1778
        }
1779 1780 1781
      } // end if (((1 << m) & mask) > 0)
    } // end for (int m=0; m < M; m++)
  } // end if TDD
1782
}
1783

1784
static void release_harq(PHY_VARS_eNB *eNB,int DLSCH_id,int tb,uint16_t frame,uint8_t subframe,uint16_t mask, int is_ack) {
1785
  /*
1786
   * Maximum number of DL transmissions = 4.
1787 1788 1789
   * TODO: get the value from configuration.
   * If is_ack is true then we release immediately. The value -1 can be used for that.
   */
1790
  do_release_harq(eNB, DLSCH_id, tb, frame, subframe, mask, is_ack ? -1 : 4);
1791
}
Raymond Knopp's avatar
Raymond Knopp committed
1792

1793 1794 1795 1796 1797
int getM(PHY_VARS_eNB *eNB,int frame,int subframe) {
  int M,Mtx=0;
  LTE_eNB_DLSCH_t *dlsch0=NULL,*dlsch1=NULL;
  LTE_DL_eNB_HARQ_t *dlsch0_harq=NULL,*dlsch1_harq=NULL;
  int harq_pid;
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1798
  int subframe_tx,frame_tx;
1799 1800
  int m;
  M=ul_ACK_subframe2_M(&eNB->frame_parms,
frtabu's avatar
frtabu committed
1801 1802
                       subframe);

1803 1804
  for (m=0; m<M; m++) {
    subframe_tx = ul_ACK_subframe2_dl_subframe(&eNB->frame_parms,
frtabu's avatar
frtabu committed
1805 1806
                  subframe,
                  m);
Wang Tsu-Han's avatar
Wang Tsu-Han committed
1807
    frame_tx =  ul_ACK_subframe2_dl_frame(&eNB->frame_parms,frame,
frtabu's avatar
frtabu committed
1808
                                          subframe,subframe_tx);
frtabu's avatar
frtabu committed
1809

frtabu's avatar
frtabu committed
1810
    if (dlsch0 == NULL || dlsch1 == NULL) {
frtabu's avatar
frtabu committed
1811 1812
      LOG_E(PHY, "dlsch0 and/or dlsch1 NULL, getM frame %i, subframe %i\n",frame,subframe);
      return Mtx;
frtabu's avatar
frtabu committed
1813 1814
    }

Wang Tsu-Han's avatar
Wang Tsu-Han committed
1815
    harq_pid = dlsch0->harq_ids[frame_tx%2][subframe_tx];
frtabu's avatar
frtabu committed
1816

1817
    if (harq_pid>=0 && harq_pid<dlsch0->Mdlharq) {
1818 1819 1820
      dlsch0_harq     = dlsch0->harq_processes[harq_pid];
      dlsch1_harq     = dlsch1->harq_processes[harq_pid];
      AssertFatal(dlsch0_harq!=NULL,"dlsch0_harq is null\n");
frtabu's avatar
frtabu committed
1821

1822
      if (dlsch0_harq->status == ACTIVE||
frtabu's avatar
frtabu committed
1823
          (dlsch1_harq!=NULL && dlsch1_harq->status == ACTIVE)) Mtx ++;
1824
    }
1825
  }
frtabu's avatar
frtabu committed
1826

Raymond Knopp's avatar
Raymond Knopp committed
1827
  return (Mtx);
1828
}
1829 1830


frtabu's avatar
frtabu committed
1831
void fill_ulsch_cqi_indication (PHY_VARS_eNB *eNB, uint16_t frame, uint8_t subframe, LTE_UL_eNB_HARQ_t *ulsch_harq, uint16_t rnti) {
Raymond Knopp's avatar
Raymond Knopp committed
1832
  pthread_mutex_lock (&eNB->UL_INFO_mutex);
1833 1834 1835
  nfapi_cqi_indication_pdu_t *pdu         = &eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_pdu_list[eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis];
  nfapi_cqi_indication_raw_pdu_t *raw_pdu = &eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_raw_pdu_list[eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis];
  pdu->instance_length = 0;
1836
  pdu->rx_ue_information.tl.tag          = NFAPI_RX_UE_INFORMATION_TAG;
1837
  pdu->rx_ue_information.rnti = rnti;
frtabu's avatar
frtabu committed
1838

Raymond Knopp's avatar
Raymond Knopp committed
1839 1840 1841 1842
  if (ulsch_harq->cqi_crc_status != 1)
    pdu->cqi_indication_rel9.data_offset = 0;
  else
    pdu->cqi_indication_rel9.data_offset = 1;   // fill in after all cqi_indications have been generated when non-zero
1843

frtabu's avatar
frtabu committed
1844
  // by default set O to rank 1 value
1845
  pdu->cqi_indication_rel9.tl.tag = NFAPI_CQI_INDICATION_REL9_TAG;
Cedric Roux's avatar
Cedric Roux committed
1846
  pdu->cqi_indication_rel9.length = (ulsch_harq->Or1>>3) + ((ulsch_harq->Or1&7) > 0 ? 1 : 0);
1847
  pdu->cqi_indication_rel9.ri[0]  = 0;
frtabu's avatar
frtabu committed
1848

1849
  // if we have RI bits, set them and if rank2 overwrite O
Raymond Knopp's avatar
Raymond Knopp committed
1850
  if (ulsch_harq->O_RI > 0) {
1851
    pdu->cqi_indication_rel9.ri[0] = ulsch_harq->o_RI[0];
frtabu's avatar
frtabu committed
1852

Raymond Knopp's avatar
Raymond Knopp committed
1853 1854
    if (ulsch_harq->o_RI[0] == 2)
      pdu->cqi_indication_rel9.length = (ulsch_harq->Or2 >> 3) + ((ulsch_harq->Or2 & 7) > 0 ? 1 : 0);
frtabu's avatar
frtabu committed
1855

1856 1857
    pdu->cqi_indication_rel9.timing_advance = 0;
  }
frtabu's avatar
frtabu committed
1858

1859
  pdu->cqi_indication_rel9.number_of_cc_reported = 1;
Raymond Knopp's avatar
Raymond Knopp committed
1860
  pdu->ul_cqi_information.channel = 1;  // PUSCH
1861
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
Raymond Knopp's avatar
Raymond Knopp committed
1862
  memcpy ((void *) raw_pdu->pdu, ulsch_harq->o, pdu->cqi_indication_rel9.length);
1863 1864 1865
  eNB->UL_INFO.cqi_ind.cqi_indication_body.tl.tag = NFAPI_CQI_INDICATION_BODY_TAG;
  eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis++;
  LOG_D(PHY,"eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis:%d\n", eNB->UL_INFO.cqi_ind.cqi_indication_body.number_of_cqis);
1866
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
frtabu's avatar
frtabu committed
1867
}
1868

frtabu's avatar
frtabu committed
1869
void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_harq, uint16_t rnti, int frame, int subframe, int bundling) {
1870
  int DLSCH_id = find_dlsch(rnti,eNB,SEARCH_EXIST);
frtabu's avatar
frtabu committed
1871

1872 1873
  if( (DLSCH_id<0) || (DLSCH_id>=NUMBER_OF_DLSCH_MAX) ) {
    LOG_E(PHY,"illegal DLSCH_id found!!! rnti %04x DLSCH_id %d\n",rnti,DLSCH_id);
1874
    return;
1875
  }
frtabu's avatar
frtabu committed
1876

1877
  //AssertFatal(DLSCH_id>=0,"DLSCH_id doesn't exist\n");
1878
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
1879
  nfapi_harq_indication_pdu_t *pdu =   &eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list[eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs];
1880 1881
  int M;
  int i;
1882 1883 1884
  eNB->UL_INFO.harq_ind.header.message_id = NFAPI_HARQ_INDICATION;
  eNB->UL_INFO.harq_ind.sfn_sf = frame<<4|subframe;
  eNB->UL_INFO.harq_ind.harq_indication_body.tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
1885 1886
  pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
1887
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
1888
  pdu->rx_ue_information.rnti                         = rnti;
frtabu's avatar
frtabu committed
1889

1890 1891 1892 1893
  if (eNB->frame_parms.frame_type == FDD) {
    pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
    pdu->harq_indication_fdd_rel13.mode = 0;
    pdu->harq_indication_fdd_rel13.number_of_ack_nack = ulsch_harq->O_ACK;
frtabu's avatar
frtabu committed
1894

1895 1896 1897 1898
    for (i = 0; i < ulsch_harq->O_ACK; i++) {
      AssertFatal (ulsch_harq->o_ACK[i] == 0 || ulsch_harq->o_ACK[i] == 1, "harq_ack[%d] is %d, should be 1,2 or 4\n", i, ulsch_harq->o_ACK[i]);
      pdu->harq_indication_fdd_rel13.harq_tb_n[i] = 2 - ulsch_harq->o_ACK[i];
      // release DLSCH if needed
1899
      release_harq(eNB,DLSCH_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
1900 1901 1902 1903 1904 1905
    }
  } else {                      // TDD
    M = ul_ACK_subframe2_M (&eNB->frame_parms, subframe);
    pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
    pdu->harq_indication_tdd_rel13.mode = 1-bundling;
    pdu->harq_indication_tdd_rel13.number_of_ack_nack = ulsch_harq->O_ACK;
frtabu's avatar
frtabu committed
1906

1907 1908 1909 1910 1911 1912 1913 1914
    for (i = 0; i < ulsch_harq->O_ACK; i++) {
      AssertFatal (ulsch_harq->o_ACK[i] == 0 || ulsch_harq->o_ACK[i] == 1, "harq_ack[%d] is %d, should be 1,2 or 4\n", i, ulsch_harq->o_ACK[i]);
      pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 2-ulsch_harq->o_ACK[i];
      // release DLSCH if needed
      /* TODO: review this code, it's most certainly wrong.
       * We have to release the proper HARQ in case of ACK or NACK if max retransmission reached.
       * Basically, call release_harq with 1 as last argument when ACK and 0 when NACK.
       */
1915
      release_harq(eNB,DLSCH_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
frtabu's avatar
frtabu committed
1916

1917 1918
      if      (M==1 && ulsch_harq->O_ACK==1 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
      else if (M==1 && ulsch_harq->O_ACK==2 && ulsch_harq->o_ACK[i] == 1) release_harq(eNB,DLSCH_id,i,frame,subframe,0xffff, ulsch_harq->o_ACK[i] == 1);
1919
      else if (M>1 && ulsch_harq->o_ACK[i] == 1) {
frtabu's avatar
frtabu committed
1920
        // spatial bundling
1921 1922
        release_harq(eNB,DLSCH_id,0,frame,subframe,1<<i, ulsch_harq->o_ACK[i] == 1);
        release_harq(eNB,DLSCH_id,1,frame,subframe,1<<i, ulsch_harq->o_ACK[i] == 1);
1923 1924
      }
    }
Cedric Roux's avatar
Cedric Roux committed
1925 1926 1927 1928 1929
  }

  //LOG_E(PHY,"eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs:%d\n", eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs);
  eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs++;
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
1930
}
1931

1932
void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) {
laurent's avatar
laurent committed
1933
  if ( split73 == SPLIT73_DU ) {
laurent's avatar
laurent committed
1934
    sendFs6Ulharq(fs6ULindicationHarq, UEid, eNB, uci, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask, 0, 0);
1935 1936 1937
    return;
  }
  
1938
  int DLSCH_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST);
frtabu's avatar
frtabu committed
1939

1940 1941
  //AssertFatal(DLSCH_id>=0,"DLSCH_id doesn't exist rnti:%x\n", uci->rnti);
  if (DLSCH_id < 0) {
1942 1943 1944
    LOG_E(PHY,"SFN/SF:%04d%d Unable to find rnti:%x do not send HARQ\n", frame, subframe, uci->rnti);
    return;
  }
frtabu's avatar
frtabu committed
1945

1946
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
1947 1948 1949 1950 1951 1952
  nfapi_harq_indication_t *ind       = &eNB->UL_INFO.harq_ind;
  nfapi_harq_indication_body_t *body = &ind->harq_indication_body;
  nfapi_harq_indication_pdu_t *pdu   = &body->harq_pdu_list[eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs];
  ind->sfn_sf = frame<<4|subframe;
  ind->header.message_id = NFAPI_HARQ_INDICATION;
  body->tl.tag = NFAPI_HARQ_INDICATION_BODY_TAG;
1953 1954
  pdu->instance_length                                = 0; // don't know what to do with this
  //  pdu->rx_ue_information.handle                       = handle;
1955
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
1956
  pdu->rx_ue_information.rnti                         = uci->rnti;
1957
  // estimate UL_CQI for MAC (from antenna port 0 only)
1958
  pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG;
Raymond Knopp's avatar
Raymond Knopp committed
1959
  int SNRtimes10 = dB_fixed_times10(uci->stat) - 10 * eNB->measurements.n0_subband_power_avg_dB;
frtabu's avatar
frtabu committed
1960

Raymond Knopp's avatar
Raymond Knopp committed
1961 1962
  if (SNRtimes10 < -100)
    LOG_I (PHY, "uci->stat %d \n", uci->stat);
frtabu's avatar
frtabu committed
1963

Raymond Knopp's avatar
Raymond Knopp committed
1964 1965 1966 1967 1968 1969
  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;
frtabu's avatar
frtabu committed
1970

1971
  pdu->ul_cqi_information.channel = 0;
frtabu's avatar
frtabu committed
1972

1973 1974
  if (eNB->frame_parms.frame_type == FDD) {
    if (uci->pucch_fmt == pucch_format1a) {
1975
      pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
frtabu's avatar
frtabu committed
1976
      pdu->harq_indication_fdd_rel13.mode = 0;
1977
      pdu->harq_indication_fdd_rel13.number_of_ack_nack = 1;
Raymond Knopp's avatar
Raymond Knopp committed
1978
      AssertFatal (harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n", harq_ack[0]);
1979 1980
      pdu->harq_indication_fdd_rel13.harq_tb_n[0] = harq_ack[0];
      // release DLSCH if needed
1981
      release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
frtabu's avatar
frtabu committed
1982
    } else if (uci->pucch_fmt == pucch_format1b) {
1983
      pdu->harq_indication_fdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_FDD_REL13_TAG;
frtabu's avatar
frtabu committed
1984
      pdu->harq_indication_fdd_rel13.mode = 0;
1985
      pdu->harq_indication_fdd_rel13.number_of_ack_nack = 2;
Raymond Knopp's avatar
Raymond Knopp committed
1986 1987
      AssertFatal (harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n", harq_ack[0]);
      AssertFatal (harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n", harq_ack[1]);
1988
      pdu->harq_indication_fdd_rel13.harq_tb_n[0] = harq_ack[0];
Raymond Knopp's avatar
Raymond Knopp committed
1989
      pdu->harq_indication_fdd_rel13.harq_tb_n[1] = harq_ack[1];
1990
      // release DLSCH if needed
1991 1992
      release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
      release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, harq_ack[1] == 1);
frtabu's avatar
frtabu committed
1993 1994
    } else AssertFatal(1==0,"only format 1a/b for now, received %d\n",uci->pucch_fmt);
  } else { // TDD
Raymond Knopp's avatar
Raymond Knopp committed
1995
    AssertFatal (tdd_mapping_mode == 0 || tdd_mapping_mode == 1 || tdd_mapping_mode == 2, "Illegal tdd_mapping_mode %d\n", tdd_mapping_mode);
1996
    pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
frtabu's avatar
frtabu committed
1997 1998 1999 2000
    pdu->harq_indication_tdd_rel13.mode = tdd_mapping_mode;
    LOG_D(PHY,"%s(eNB, uci_harq format %d, rnti:%04x, frame:%d, subframe:%d, tdd_mapping_mode:%d) harq_ack[0]:%d harq_ack[1]:%d\n", __FUNCTION__, uci->pucch_fmt,uci->rnti, frame, subframe,
          tdd_mapping_mode,harq_ack[0],harq_ack[1]);

2001
    switch (tdd_mapping_mode) {
frtabu's avatar
frtabu committed
2002 2003 2004 2005 2006 2007 2008 2009
      case 0:                    // bundling
        if (uci->pucch_fmt == pucch_format1a) {
          pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
          pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1;
          LOG_D(PHY,"bundling, pucch1a, number of ack nack %d\n",pdu->harq_indication_tdd_rel13.number_of_ack_nack);
          AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n",harq_ack[0]);
          pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = harq_ack[0];
          // release all bundled DLSCH if needed
2010
          release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
frtabu's avatar
frtabu committed
2011 2012 2013 2014 2015 2016 2017 2018
        } else if (uci->pucch_fmt == pucch_format1b) {
          pdu->harq_indication_tdd_rel13.number_of_ack_nack = 2;
          AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n",harq_ack[0]);
          AssertFatal(harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n",harq_ack[1]);
          pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
          pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = harq_ack[0];
          pdu->harq_indication_tdd_rel13.harq_data[1].bundling.value_0 = harq_ack[1];
          // release all DLSCH if needed
2019 2020
          release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
          release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, harq_ack[1] == 1);
frtabu's avatar
frtabu committed
2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033
        }

        break;

      case 1:                    // multiplexing
        AssertFatal (uci->pucch_fmt == pucch_format1b, "uci->pucch_format %d is not format1b\n", uci->pucch_fmt);

        if (uci->num_pucch_resources == 1 && uci->pucch_fmt == pucch_format1a) {
          pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
          pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1;
          AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[0] == 4, "harq_ack[0] is %d, should be 1,2 or 4\n",harq_ack[0]);
          pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0];
          // release all DLSCH if needed
2034
          release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
frtabu's avatar
frtabu committed
2035 2036 2037 2038 2039 2040 2041 2042
        } else if (uci->num_pucch_resources == 1 && uci->pucch_fmt == pucch_format1b) {
          pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
          pdu->harq_indication_tdd_rel13.number_of_ack_nack = 2;
          AssertFatal(harq_ack[0] == 1 || harq_ack[0] == 2 || harq_ack[1] == 4, "harq_ack[0] is %d, should be 0,1 or 4\n",harq_ack[0]);
          AssertFatal(harq_ack[1] == 1 || harq_ack[1] == 2 || harq_ack[1] == 4, "harq_ack[1] is %d, should be 0,1 or 4\n",harq_ack[1]);
          pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0];
          pdu->harq_indication_tdd_rel13.harq_data[1].multiplex.value_0 = harq_ack[1];
          // release all DLSCH if needed
2043 2044
          release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, harq_ack[0] == 1);
          release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, harq_ack[1] == 1);
frtabu's avatar
frtabu committed
2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055
        } else { // num_pucch_resources (M) > 1
          pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
          pdu->harq_indication_tdd_rel13.number_of_ack_nack = uci->num_pucch_resources;
          pdu->harq_indication_tdd_rel13.harq_data[0].multiplex.value_0 = harq_ack[0];
          pdu->harq_indication_tdd_rel13.harq_data[1].multiplex.value_0 = harq_ack[1];

          if (uci->num_pucch_resources == 3)  pdu->harq_indication_tdd_rel13.harq_data[2].multiplex.value_0 = harq_ack[2];

          if (uci->num_pucch_resources == 4)  pdu->harq_indication_tdd_rel13.harq_data[3].multiplex.value_0 = harq_ack[3];

          // spatial-bundling in this case so release both HARQ if necessary
2056 2057
          release_harq(eNB,DLSCH_id,0,frame,subframe,tdd_multiplexing_mask, 1 /* force release? previous code was unconditional */);
          release_harq(eNB,DLSCH_id,1,frame,subframe,tdd_multiplexing_mask, 1 /* force release? previous code was unconditional */);
frtabu's avatar
frtabu committed
2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080
        }

        break;

      case 2: // special bundling (SR collision)
        pdu->harq_indication_tdd_rel13.tl.tag = NFAPI_HARQ_INDICATION_TDD_REL13_TAG;
        pdu->harq_indication_tdd_rel13.number_of_ack_nack = 1;
        pdu->harq_indication_tdd_rel13.mode = 0;
        int tdd_config5_sf2scheds=0;

        if (eNB->frame_parms.tdd_config==5) tdd_config5_sf2scheds = getM(eNB,frame,subframe);

        switch (harq_ack[0]) {
          case 0:
          case 4:
            pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0;
            /* TODO: release_harq here? this whole code looks suspicious */
            break;

          case 1: // check if M=1,4,7
            if (uci->num_pucch_resources == 1 || uci->num_pucch_resources == 4 ||
                tdd_config5_sf2scheds == 1 || tdd_config5_sf2scheds == 4 || tdd_config5_sf2scheds == 7) {
              pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1;
2081 2082
              release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, 1);
              release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, 1);
frtabu's avatar
frtabu committed
2083 2084 2085 2086 2087 2088 2089 2090 2091 2092
            } else {
              pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0;
            }

            break;

          case 2: // check if M=2,5,8
            if (uci->num_pucch_resources == 2 || tdd_config5_sf2scheds == 2 ||
                tdd_config5_sf2scheds == 5 || tdd_config5_sf2scheds == 8) {
              pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1;
2093 2094
              release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, 1);
              release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, 1);
frtabu's avatar
frtabu committed
2095 2096 2097 2098 2099 2100 2101 2102 2103 2104
            } else {
              pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0;
            }

            break;

          case 3: // check if M=3,6,9
            if (uci->num_pucch_resources == 3 || tdd_config5_sf2scheds == 3 ||
                tdd_config5_sf2scheds == 6 || tdd_config5_sf2scheds == 9) {
              pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 1;
2105 2106
              release_harq(eNB,DLSCH_id,0,frame,subframe,0xffff, 1);
              release_harq(eNB,DLSCH_id,1,frame,subframe,0xffff, 1);
frtabu's avatar
frtabu committed
2107 2108 2109 2110 2111 2112 2113 2114
            } else {
              pdu->harq_indication_tdd_rel13.harq_data[0].bundling.value_0 = 0;
            }

            break;
        }

        break;
2115
    }
Raymond Knopp's avatar
Raymond Knopp committed
2116
  }                             //TDD
frtabu's avatar
frtabu committed
2117

2118 2119
  eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs++;
  LOG_D(PHY,"Incremented eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs:%d\n", eNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs);
frtabu's avatar
frtabu committed
2120
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
2121
}
2122

2123
void fill_crc_indication (PHY_VARS_eNB *eNB, int ULSCH_id, int frame, int subframe, uint8_t crc_flag) {
2124
  pthread_mutex_lock(&eNB->UL_INFO_mutex);
2125 2126 2127 2128
  nfapi_crc_indication_pdu_t *pdu =   &eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list[eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs];
  eNB->UL_INFO.crc_ind.sfn_sf                         = frame<<4 | subframe;
  eNB->UL_INFO.crc_ind.header.message_id              = NFAPI_CRC_INDICATION;
  eNB->UL_INFO.crc_ind.crc_indication_body.tl.tag     = NFAPI_CRC_INDICATION_BODY_TAG;
Raymond Knopp's avatar
Raymond Knopp committed
2129
  pdu->instance_length = 0;     // don't know what to do with this
2130
  //  pdu->rx_ue_information.handle                       = handle;
2131
  pdu->rx_ue_information.tl.tag                       = NFAPI_RX_UE_INFORMATION_TAG;
2132
  pdu->rx_ue_information.rnti                         = eNB->ulsch[ULSCH_id]->rnti;
Cedric Roux's avatar
Cedric Roux committed
2133
  pdu->crc_indication_rel8.tl.tag                     = NFAPI_CRC_INDICATION_REL8_TAG;
2134
  pdu->crc_indication_rel8.crc_flag                   = crc_flag;
2135 2136
  eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs++;
  //LOG_D(PHY, "%s() rnti:%04x crcs:%d crc_flag:%d\n", __FUNCTION__, pdu->rx_ue_information.rnti, eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs, crc_flag);
2137 2138
  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
}
2139

frtabu's avatar
frtabu committed
2140
void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) {
2141
  //RX processing for ue-specific resources (i
Raymond Knopp's avatar
Raymond Knopp committed
2142 2143 2144
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
  const int       subframe = proc->subframe_rx;
  const int       frame = proc->frame_rx;
Cedric Roux's avatar
Cedric Roux committed
2145
  /* TODO: use correct rxdata */
Raymond Knopp's avatar
Raymond Knopp committed
2146 2147
  T (T_ENB_PHY_INPUT_SIGNAL, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (0),
     T_BUFFER (&eNB->RU_list[0]->common.rxdata[0][subframe * eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti * 4));
frtabu's avatar
frtabu committed
2148

Cedric Roux's avatar
Cedric Roux committed
2149
  if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return;
frtabu's avatar
frtabu committed
2150

Cedric Roux's avatar
Cedric Roux committed
2151
  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
2152
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 );
Raymond Knopp's avatar
Raymond Knopp committed
2153 2154 2155 2156 2157
  LOG_D (PHY, "[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n", eNB->Mod_id, frame, subframe);
  eNB->rb_mask_ul[0] = 0;
  eNB->rb_mask_ul[1] = 0;
  eNB->rb_mask_ul[2] = 0;
  eNB->rb_mask_ul[3] = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2158
  // Fix me here, these should be locked
Cedric Roux's avatar
Cedric Roux committed
2159 2160
  eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus  = 0;
  eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2161
  // Call SRS first since all others depend on presence of SRS or lack thereof
Raymond Knopp's avatar
Raymond Knopp committed
2162
  srs_procedures (eNB, proc);
2163
  eNB->first_run_I0_measurements = 0;
Raymond Knopp's avatar
Raymond Knopp committed
2164
  uci_procedures (eNB, proc);
frtabu's avatar
frtabu committed
2165 2166

  if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // If PNF or monolithic
2167 2168
    pusch_procedures(eNB,proc);
  }
2169

Raymond Knopp's avatar
Raymond Knopp committed
2170
  lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements);
2171
  int min_I0=1000,max_I0=0;
Raymond Knopp's avatar
Raymond Knopp committed
2172
  int amin=0,amax=0;
2173
  if ((frame==0) && (subframe==3)) {
frtabu's avatar
frtabu committed
2174
    for (int i=0; i<eNB->frame_parms.N_RB_UL; i++) {
2175
      if (i==(eNB->frame_parms.N_RB_UL>>1) - 1) i+=2;
frtabu's avatar
frtabu committed
2176

Raymond Knopp's avatar
Raymond Knopp committed
2177
      if (eNB->measurements.n0_subband_power_tot_dB[i]<min_I0) {min_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; amin=i;}
frtabu's avatar
frtabu committed
2178

Raymond Knopp's avatar
Raymond Knopp committed
2179
      if (eNB->measurements.n0_subband_power_tot_dB[i]>max_I0) {max_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; amax=i;}
2180
    }
frtabu's avatar
frtabu committed
2181

Raymond Knopp's avatar
Raymond Knopp committed
2182
    LOG_I (PHY, "max_I0 %d (rb %d), min_I0 %d (rb %d), avg I0 %d\n", max_I0, amax, min_I0, amin, eNB->measurements.n0_subband_power_avg_dB);
2183
  }
frtabu's avatar
frtabu committed
2184

2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201
  // clear unused statistics after 2 seconds
  for (int i=0;i<NUMBER_OF_SCH_STATS_MAX;i++) {
     if (eNB->ulsch_stats[i].frame <= frame) {
         if ((eNB->ulsch_stats[i].frame + 200) < frame) eNB->ulsch_stats[i].rnti = 0;
     }
     else {
         if (eNB->ulsch_stats[i].frame + 200 < (frame+1024)) eNB->ulsch_stats[i].rnti = 0;
     }
     if (eNB->uci_stats[i].frame <= frame) {
         if ((eNB->uci_stats[i].frame + 200) < frame) eNB->uci_stats[i].rnti = 0;
     }
     else {
         if (eNB->uci_stats[i].frame + 200 < (frame+1024)) eNB->uci_stats[i].rnti = 0;
     }
  }


2202
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 );
Raymond Knopp's avatar
Raymond Knopp committed
2203
}
2204

2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217
void release_rnti_of_phy(module_id_t mod_id) {
  int i,j;
  int CC_id;
  rnti_t rnti;
  PHY_VARS_eNB *eNB_PHY = NULL;
  LTE_eNB_ULSCH_t *ulsch = NULL;
  LTE_eNB_DLSCH_t *dlsch = NULL;

  for(i = 0; i< release_rntis.number_of_TLVs; i++) {
    for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
      eNB_PHY = RC.eNB[mod_id][CC_id];
      rnti = release_rntis.ue_release_request_TLVs_list[i].rnti;

2218
      for (j=0; j<NUMBER_OF_ULSCH_MAX; j++) {
2219 2220 2221 2222 2223 2224
        ulsch = eNB_PHY->ulsch[j];

        if((ulsch != NULL) && (ulsch->rnti == rnti)) {
          LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti);
          clean_eNb_ulsch(ulsch);
        }
2225

2226
        dlsch = eNB_PHY->dlsch[j][0];
2227

2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238
        if((dlsch != NULL) && (dlsch->rnti == rnti)) {
          LOG_I(PHY, "clean_eNb_dlsch dlsch[%d] UE %x \n", j, rnti);
          clean_eNb_dlsch(dlsch);
        }
      }

      ulsch = eNB_PHY->ulsch[j];

      if((ulsch != NULL) && (ulsch->rnti == rnti)) {
        LOG_I(PHY, "clean_eNb_ulsch ulsch[%d] UE %x\n", j, rnti);
        clean_eNb_ulsch(ulsch);
2239 2240
        for (j=0;j<NUMBER_OF_ULSCH_MAX;j++)
           if (eNB_PHY->ulsch_stats[j].rnti == rnti) {eNB_PHY->ulsch_stats[j].rnti=0; break;}
2241 2242
      }

2243
      for(j=0; j<NUMBER_OF_UCI_MAX; j++) {
2244 2245 2246
        if(eNB_PHY->uci_vars[j].rnti == rnti) {
          LOG_I(PHY, "clean eNb uci_vars[%d] UE %x \n",j, rnti);
          memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI));
2247
        }
2248
      }
2249
    }
2250 2251 2252
  }

  memset(&release_rntis, 0, sizeof(nfapi_ue_release_request_body_t));
2253
}