phy_procedures_lte_ue.c 157 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22 23

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

33
#include "assertions.h"
34 35 36 37 38 39
#include "defs.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"

Florian Kaltenberger's avatar
Florian Kaltenberger committed
40
#define DEBUG_PHY_PROC
41 42 43 44 45 46 47 48 49 50 51 52 53 54

#ifndef PUCCH
#define PUCCH
#endif

#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/defs.h"
#include "UTIL/LOG/log.h"

#ifdef EMOS
fifo_dump_emos_UE emos_dump_UE;
#endif

#include "UTIL/LOG/vcd_signal_dumper.h"
55
#include "UTIL/OPT/opt.h"
56

57 58 59 60
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

61 62 63
#include "PHY/defs.h"

#include "PHY/CODING/extern.h"
64

Bilel's avatar
Bilel committed
65 66
#include "T.h"

67 68 69 70 71 72 73
#define DLSCH_RB_ALLOC 0x1fbf  // skip DC RB (total 23/25 RBs)
#define DLSCH_RB_ALLOC_12 0x0aaa  // skip DC RB (total 23/25 RBs)

#define NS_PER_SLOT 500000

extern int oai_exit;

Bilel's avatar
Bilel committed
74
extern double cpuf;
75 76 77



Florian Kaltenberger's avatar
Florian Kaltenberger committed
78
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
79
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
80 81
#endif

82

83

84
void dump_dlsch(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid)
85
{
86
  unsigned int coded_bits_per_codeword;
87 88 89
  uint8_t nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12;

  coded_bits_per_codeword = get_G(&ue->frame_parms,
90 91 92 93
                                  ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->nb_rb,
                                  ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even,
                                  ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->Qm,
                                  ue->dlsch[subframe&0x1][eNB_id][0]->harq_processes[harq_pid]->Nl,
Bilel's avatar
Bilel committed
94
                                  ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
95
                                  proc->frame_rx,
96
				  subframe,
97
				  ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]);
98

99 100 101
  write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,2,1);
  write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars[subframe&0x1][0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
  write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars[subframe&0x1][0]->dl_ch_estimates_ext[0],300*nsymb,1,1);
102
  /*
103 104 105 106
    write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1);
    write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1);
    write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1);
    write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1);
107
  */
108 109
  write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars[subframe&0x1][0]->rxdataF_comp0[0],300*12,1,1);
  write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars[subframe&0x1][0]->llr[0],coded_bits_per_codeword,1,0);
110

111 112
  write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars[subframe&0x1][0]->dl_ch_mag0,300*12,1,1);
  write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars[subframe&0x1][0]->dl_ch_magb0,300*12,1,1);
113 114
}

115
void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe)
116
{
117
  unsigned int coded_bits_per_codeword;
118
  uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12);
119

120 121 122
  coded_bits_per_codeword = get_G(&ue->frame_parms,
                                  ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb,
                                  ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even,
123
                                  2,
124
                                  1,
Bilel's avatar
Bilel committed
125
                                  ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
126
                                  proc->frame_rx,
127
				  subframe,
128
				  0);
129
  LOG_D(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n",
130 131
        ue->Mod_id,
	ue->frame_parms.ofdm_symbol_size,
132
	nsymb,
133 134 135
        ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb,
        ue->dlsch_SI[eNB_id]->harq_processes[0]->mcs,
        ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb,
Bilel's avatar
Bilel committed
136
        ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
137
        coded_bits_per_codeword);
138

139
  write_output("rxsig0.m","rxs0", &ue->common_vars.rxdata[0][subframe*ue->frame_parms.samples_per_tti],ue->frame_parms.samples_per_tti,1,1);
140

141
  write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0],nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
142 143
  write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_SI[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
  write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_SI[0]->dl_ch_estimates_ext[0],ue->frame_parms.N_RB_DL*12*nsymb,1,1);
144
  /*
145 146 147 148
    write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1);
    write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1);
    write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1);
    write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1);
149
  */
150 151
  write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_SI[0]->rxdataF_comp0[0],ue->frame_parms.N_RB_DL*12*nsymb,1,1);
  write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_SI[0]->llr[0],coded_bits_per_codeword,1,0);
152

153 154
  write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_SI[0]->dl_ch_mag0,300*nsymb,1,1);
  write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_SI[0]->dl_ch_magb0,300*nsymb,1,1);
155
  sleep(1);
156 157 158
  exit(-1);
}

Florian Kaltenberger's avatar
Florian Kaltenberger committed
159
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
knopp's avatar
 
knopp committed
160 161
//unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162};
/*
162 163
  unsigned int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL)
  {
164

165
  int gain_dB = power_dBm - power_max_dBm;
knopp's avatar
 
knopp committed
166 167 168 169
  int amp_x_100;

  switch (N_RB_UL) {
  case 6:
170 171
  amp_x_100 = AMP;      // PRACH is 6 PRBS so no scale
  break;
knopp's avatar
 
knopp committed
172
  case 15:
173 174
  amp_x_100 = 158*AMP;  // 158 = 100*sqrt(15/6)
  break;
knopp's avatar
 
knopp committed
175
  case 25:
176 177
  amp_x_100 = 204*AMP;  // 204 = 100*sqrt(25/6)
  break;
knopp's avatar
 
knopp committed
178
  case 50:
179 180
  amp_x_100 = 286*AMP;  // 286 = 100*sqrt(50/6)
  break;
knopp's avatar
 
knopp committed
181
  case 75:
182 183
  amp_x_100 = 354*AMP;  // 354 = 100*sqrt(75/6)
  break;
knopp's avatar
 
knopp committed
184
  case 100:
185 186
  amp_x_100 = 408*AMP;  // 408 = 100*sqrt(100/6)
  break;
knopp's avatar
 
knopp committed
187
  default:
188 189 190
  LOG_E(PHY,"Unknown PRB size %d\n",N_RB_UL);
  mac_xface->macphy_exit("");
  break;
knopp's avatar
 
knopp committed
191
  }
192
  if (gain_dB < -30) {
193
  return(amp_x_100/3162);
194
  } else if (gain_dB>0)
195
  return(amp_x_100);
196
  else
197 198
  return(amp_x_100/gain_table[-gain_dB]);  // 245 corresponds to the factor sqrt(25/6)
  }
knopp's avatar
 
knopp committed
199 200 201 202 203 204 205 206 207
*/

unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb)
{

  int gain_dB = power_dBm - power_max_dBm;
  double gain_lin;

  gain_lin = pow(10,.1*gain_dB);
208 209
  AssertFatal((nb_rb >0) && (nb_rb <= N_RB_UL),"Illegal nb_rb/N_RB_UL combination (%d/%d)\n",nb_rb,N_RB_UL);
  return((int)(AMP*sqrt(gain_lin*N_RB_UL/(double)nb_rb)));
knopp's avatar
 
knopp committed
210 211
}

212 213
#endif

214
void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe)
215
{
216
  unsigned int coded_bits_per_codeword;
217
  uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12);
218

219 220 221
  coded_bits_per_codeword = get_G(&ue->frame_parms,
                                  ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb,
                                  ue->dlsch_ra[eNB_id]->harq_processes[0]->rb_alloc_even,
222
                                  2,
223
                                  1,
Bilel's avatar
Bilel committed
224
                                  ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
225
                                  proc->frame_rx,
226
				  subframe,
227
				  0);
228
  LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n",
229 230 231 232
        ue->Mod_id,
        ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb,
        ue->dlsch_ra[eNB_id]->harq_processes[0]->mcs,
        ue->dlsch_ra[eNB_id]->harq_processes[0]->nb_rb,
Bilel's avatar
Bilel committed
233
        ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
234
        coded_bits_per_codeword);
235

236
  write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[subframe&0x1].rxdataF[0],2*12*ue->frame_parms.ofdm_symbol_size,2,1);
237 238
  write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_ra[0]->rxdataF_ext[0],2*12*ue->frame_parms.ofdm_symbol_size,1,1);
  write_output("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_ra[0]->dl_ch_estimates_ext[0],300*nsymb,1,1);
239
  /*
240 241 242 243
    write_output("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1);
    write_output("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1);
    write_output("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1);
    write_output("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1);
244
  */
245 246
  write_output("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_ra[0]->rxdataF_comp0[0],300*nsymb,1,1);
  write_output("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_ra[0]->llr[0],coded_bits_per_codeword,1,0);
247

248 249
  write_output("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_ra[0]->dl_ch_mag0,300*nsymb,1,1);
  write_output("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_ra[0]->dl_ch_magb0,300*nsymb,1,1);
250
}
251

252 253
void phy_reset_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
254 255 256

  // This flushes ALL DLSCH and ULSCH harq buffers of ALL connected eNBs...add the eNB_index later
  // for more flexibility
257

258
  uint8_t i,j,k,s;
259
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
260

Bilel's avatar
Bilel committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
  //[NUMBER_OF_RX_THREAD=2][NUMBER_OF_CONNECTED_eNB_MAX][2];
  for(int l=0; l<2; l++) {
      for(i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
          for(j=0; j<2; j++) {
              //DL HARQ
              if(ue->dlsch[l][i][j]) {
                  for(k=0; k<NUMBER_OF_HARQ_PID_MAX && ue->dlsch[l][i][j]->harq_processes[k]; k++) {
                      ue->dlsch[l][i][j]->harq_processes[k]->status = SCH_IDLE;
                      for (s=0; s<10; s++) {
                          // reset ACK/NACK bit to DTX for all subframes s = 0..9
                          ue->dlsch[l][i][j]->harq_ack[s].ack = 2;
                          ue->dlsch[l][i][j]->harq_ack[s].send_harq_status = 0;
                          ue->dlsch[l][i][j]->harq_ack[s].vDAI_UL = 0xff;
                          ue->dlsch[l][i][j]->harq_ack[s].vDAI_DL = 0xff;
                      }
                  }
              }
278
          }
279

Bilel's avatar
Bilel committed
280 281 282 283 284 285
          //UL HARQ
          if(ue->ulsch[i]) {
              for(k=0; k<NUMBER_OF_HARQ_PID_MAX && ue->ulsch[i]->harq_processes[k]; k++) {
                  ue->ulsch[i]->harq_processes[k]->status = SCH_IDLE;
                  //Set NDIs for all UL HARQs to 0
                  //  ue->ulsch[i]->harq_processes[k]->Ndi = 0;
286

Bilel's avatar
Bilel committed
287 288
              }
          }
289

Bilel's avatar
Bilel committed
290 291
          // flush Msg3 buffer
          ue->ulsch_Msg3_active[i] = 0;
292

Bilel's avatar
Bilel committed
293
      }
294 295 296
  }
}

297 298
void ra_failed(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
299 300

  // if contention resolution fails, go back to PRACH
knopp's avatar
 
knopp committed
301
  PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PRACH;
Bilel's avatar
Bilel committed
302 303 304 305
  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti_is_temporary = 0;
  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti = 0;
  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti_is_temporary = 0;
  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti = 0;
306
  LOG_E(PHY,"[UE %d] Random-access procedure fails, going back to PRACH, setting SIStatus = 0, discard temporary C-RNTI and State RRC_IDLE\n",Mod_id);
307 308
}

309 310
void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
311 312 313

  int i;

314
  LOG_I(PHY,"[UE %d][RAPROC] Random-access procedure succeeded. Set C-RNTI = Temporary C-RNTI\n",Mod_id);
315

Bilel's avatar
Bilel committed
316 317
  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_index]->crnti_is_temporary = 0;
  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_index]->crnti_is_temporary = 0;
318
  PHY_vars_UE_g[Mod_id][CC_id]->ulsch_Msg3_active[eNB_index] = 0;
knopp's avatar
 
knopp committed
319
  PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PUSCH;
320

321
  for (i=0; i<8; i++) {
322
    if (PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]) {
323
      PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->status=SCH_IDLE;
Bilel's avatar
Bilel committed
324 325
      PHY_vars_UE_g[Mod_id][CC_id]->dlsch[0][eNB_index][0]->harq_processes[i]->round=0;
      PHY_vars_UE_g[Mod_id][CC_id]->dlsch[1][eNB_index][0]->harq_processes[i]->round=0;
326
    }
327 328 329 330 331
  }


}

332 333
UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
334

knopp's avatar
 
knopp committed
335
  return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index]);
336 337

}
338
void process_timing_advance_rar(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint16_t timing_advance) {
339

340
  ue->timing_advance = timing_advance*4;
341 342


343
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
344 345 346
  /* TODO: fix this log, what is 'HW timing advance'? */
  /*LOG_I(PHY,"[UE %d] AbsoluteSubFrame %d.%d, received (rar) timing_advance %d, HW timing advance %d\n",ue->Mod_id,proc->frame_rx, proc->subframe_rx, ue->timing_advance);*/
  LOG_I(PHY,"[UE %d] AbsoluteSubFrame %d.%d, received (rar) timing_advance %d\n",ue->Mod_id,proc->frame_rx, proc->subframe_rx, ue->timing_advance);
347 348 349 350
#endif

}

351 352
void process_timing_advance(uint8_t Mod_id,uint8_t CC_id,int16_t timing_advance)
{
353

gauthier's avatar
gauthier committed
354
  //  uint32_t frame = PHY_vars_UE_g[Mod_id]->frame;
355

356
  // timing advance has Q1.5 format
357
  timing_advance = timing_advance - 31;
358

359 360
  PHY_vars_UE_g[Mod_id][CC_id]->timing_advance = PHY_vars_UE_g[Mod_id][CC_id]->timing_advance+timing_advance*4; //this is for 25RB only!!!

361

362
  LOG_D(PHY,"[UE %d] Got timing advance %d from MAC, new value %d\n",Mod_id, timing_advance, PHY_vars_UE_g[Mod_id][CC_id]->timing_advance);
363

364 365 366

}

367
uint8_t is_SR_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
368 369
{

370 371
  int subframe=proc->subframe_tx;

372
  LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Checking for SR TXOp (sr_ConfigIndex %d)\n",
Bilel's avatar
Bilel committed
373
        ue->Mod_id,ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->crnti,proc->frame_tx,subframe,
374
        ue->scheduling_request_config[eNB_id].sr_ConfigIndex);
375

376 377
  if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 4) {        // 5 ms SR period
    if ((subframe%5) == ue->scheduling_request_config[eNB_id].sr_ConfigIndex)
378
      return(1);
379 380
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 14) { // 10 ms SR period
    if (subframe==(ue->scheduling_request_config[eNB_id].sr_ConfigIndex-5))
381
      return(1);
382
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 34) { // 20 ms SR period
383
    if ((10*(proc->frame_tx&1)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15))
384
      return(1);
385
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 74) { // 40 ms SR period
386
    if ((10*(proc->frame_tx&3)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35))
387
      return(1);
388
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 154) { // 80 ms SR period
389
    if ((10*(proc->frame_tx&7)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75))
390 391 392 393 394 395
      return(1);
  }

  return(0);
}

396 397 398 399 400 401 402 403 404 405 406
uint8_t is_cqi_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
{
  int subframe = proc->subframe_tx;
  int frame    = proc->frame_tx;
  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;

  //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for CQI TXOp (cqi_ConfigIndex %d) isCQIOp %d\n",
  //      ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,subframe,
  //      cqirep->cqi_PMI_ConfigIndex,
  //      (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI));

407 408 409
  if (cqirep->cqi_PMI_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI)
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
    return(1);
  else
    return(0);
}
uint8_t is_ri_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
{


  int subframe = proc->subframe_tx;
  int frame    = proc->frame_tx;
  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;
  int log2Mri = cqirep->ri_ConfigIndex/161;
  int N_OFFSET_RI = cqirep->ri_ConfigIndex % 161;

  //LOG_I(PHY,"[UE %d][CRNTI %x] AbsSubFrame %d.%d Checking for RI TXOp (ri_ConfigIndex %d) isRIOp %d\n",
  //      ue->Mod_id,ue->pdcch_vars[eNB_id]->crnti,frame,subframe,
  //      cqirep->ri_ConfigIndex,
  //      (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0));
428 429 430
  if (cqirep->ri_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0)
431 432 433 434 435
    return(1);
  else
    return(0);
}

Bilel's avatar
Bilel committed
436 437 438 439 440 441 442 443
void compute_cqi_ri_resources(PHY_VARS_UE *ue,
                              LTE_UE_ULSCH_t *ulsch,
                              uint8_t eNB_id,
                              uint16_t rnti,
                              uint16_t p_rnti,
                              uint16_t cba_rnti,
                              uint8_t cqi_status,
                              uint8_t ri_status)
Bilel's avatar
Bilel committed
444
{
445 446
    //PHY_MEASUREMENTS *meas = &ue->measurements;
    //uint8_t transmission_mode = ue->transmission_mode[eNB_id];
Bilel's avatar
Bilel committed
447 448


449
    //LOG_I(PHY,"compute_cqi_ri_resources O_RI %d O %d uci format %d \n",ulsch->O_RI,ulsch->O,ulsch->uci_format);
Bilel's avatar
Bilel committed
450
    if (cqi_status == 1 || ri_status == 1)
Bilel's avatar
Bilel committed
451
    {
Bilel's avatar
Bilel committed
452
        ulsch->O = 4;
Bilel's avatar
Bilel committed
453 454 455
    }
}

456
void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t isSubframeSRS) 
Bilel's avatar
Bilel committed
457
{
458 459 460 461 462 463 464 465 466
  
  LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
  int frame_tx    = proc->frame_tx;
  int subframe_tx = proc->subframe_tx;
  SOUNDINGRS_UL_CONFIG_DEDICATED *pSoundingrs_ul_config_dedicated=&ue->soundingrs_ul_config_dedicated[eNB_id];
  uint16_t srsPeriodicity;
  uint16_t srsOffset;
  uint8_t is_pucch2_subframe = 0;
  uint8_t is_sr_an_subframe  = 0;
Bilel's avatar
Bilel committed
467 468 469

  // check for SRS opportunity
  pSoundingrs_ul_config_dedicated->srsUeSubframe   = 0;
470
  pSoundingrs_ul_config_dedicated->srsCellSubframe = isSubframeSRS;
Bilel's avatar
Bilel committed
471

472 473
  if (isSubframeSRS) {  
    LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup);
fnabet's avatar
fnabet committed
474 475
      if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup)
      {
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
          compute_srs_pos(frame_parms->frame_type, pSoundingrs_ul_config_dedicated->srs_ConfigIndex, &srsPeriodicity, &srsOffset);

          LOG_D(PHY," srsPeriodicity: %d srsOffset: %d isSubframeSRS %d \n",srsPeriodicity,srsOffset,isSubframeSRS);

          // transmit SRS if the four following constraints are respected:
          // - UE is configured to transmit SRS
          // - SRS are configured in current subframe
          // - UE is configured to send SRS in this subframe

          // 36.213 8.2
          // 1- A UE shall not transmit SRS whenever SRS and PUCCH format 2/2a/2b transmissions happen to coincide in the same subframe
          // 2- A UE shall not transmit SRS whenever SRS transmit
          //    on and PUCCH transmission carrying ACK/NACK and/or
          //    positive SR happen to coincide in the same subframe if the parameter
          //    Simultaneous-AN-and-SRS is FALSE

          // check PUCCH format 2/2a/2b transmissions
          is_pucch2_subframe = is_cqi_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.cqi_PMI_ConfigIndex>0);
          is_pucch2_subframe = (is_ri_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0)) || is_pucch2_subframe;

          // check ACK/SR transmission
          if(frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission == FALSE)
          {
              if(is_SR_TXOp(ue,proc,eNB_id))
              {
                  uint32_t SR_payload = 0;
                  if (ue->mac_enabled==1)
                  {
                      int Mod_id = ue->Mod_id;
                      int CC_id = ue->CC_id;
506
                      // Panos: Substitute call to ue_get_SR() with the filled ue_SR_config->SR_payload (0, or 1).
507 508 509 510 511 512
                      SR_payload = ue_get_SR(Mod_id,
					     CC_id,
					     frame_tx,
					     eNB_id,
					     ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->crnti,
					     subframe_tx); // subframe used for meas gap
513 514 515 516 517 518 519 520

                      if (SR_payload > 0)
                          is_sr_an_subframe = 1;
                  }
              }

              uint8_t pucch_ack_payload[2];
              if (get_ack(&ue->frame_parms,
521
                      ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack,
Bilel's avatar
Bilel committed
522
                      subframe_tx,proc->subframe_rx,pucch_ack_payload,0) > 0)
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
              {
                  is_sr_an_subframe = 1;
              }
          }

          // check SRS UE opportunity
          if( isSubframeSRS  &&
                  (((10*frame_tx+subframe_tx) % srsPeriodicity) == srsOffset)
          )
          {
              if ((is_pucch2_subframe == 0) && (is_sr_an_subframe == 0))
              {
                  pSoundingrs_ul_config_dedicated->srsUeSubframe = 1;
                  ue->ulsch[eNB_id]->srs_active   = 1;
                  ue->ulsch[eNB_id]->Nsymb_pusch  = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active;
              }
              else
              {
                  LOG_I(PHY,"DROP UE-SRS-TX for this subframe %d.%d: collision with PUCCH2 or SR/AN: PUCCH2-occasion: %d, SR-AN-occasion[simSRS-SR-AN %d]: %d  \n", frame_tx, subframe_tx, is_pucch2_subframe, frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission, is_sr_an_subframe);
              }
          }
fnabet's avatar
fnabet committed
544
      }
fnabet's avatar
fnabet committed
545
      LOG_D(PHY," srsCellSubframe: %d, srsUeSubframe: %d, Nsymb-pusch: %d \n", pSoundingrs_ul_config_dedicated->srsCellSubframe, pSoundingrs_ul_config_dedicated->srsUeSubframe, ue->ulsch[eNB_id]->Nsymb_pusch);
Bilel's avatar
Bilel committed
546 547 548
  }
}

549

knopp's avatar
knopp committed
550 551 552 553 554 555 556 557 558 559 560 561
void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id)
{

  CQI_REPORTPERIODIC *cqirep = &ue->cqi_report_config[eNB_id].CQI_ReportPeriodic;
  int cqi_PMI_ConfigIndex = cqirep->cqi_PMI_ConfigIndex;

  if (ue->frame_parms.frame_type == FDD) {
    if (cqi_PMI_ConfigIndex <= 1) {        // 2 ms CQI_PMI period
      cqirep->Npd = 2;
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex;
    } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period
      cqirep->Npd = 5;
562
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-2;
knopp's avatar
knopp committed
563 564
    } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
      cqirep->Npd = 10;
565
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-7;
knopp's avatar
knopp committed
566 567
    } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
      cqirep->Npd = 20;
568
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-17;
knopp's avatar
knopp committed
569 570
    } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
      cqirep->Npd = 40;
571
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-37;
knopp's avatar
knopp committed
572 573
    } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
      cqirep->Npd = 80;
574
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-77;
knopp's avatar
knopp committed
575 576
    } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
      cqirep->Npd = 160;
577
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-157;
knopp's avatar
knopp committed
578 579 580 581 582
    }
    else if (cqi_PMI_ConfigIndex > 317) {
      
      if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period
	cqirep->Npd = 32;
583
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-318;
knopp's avatar
knopp committed
584 585 586
      }
      else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period
	cqirep->Npd = 64;
587
	cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-350;
knopp's avatar
knopp committed
588 589 590
      }
      else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period
	cqirep->Npd = 128;
591
	cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-414;
knopp's avatar
knopp committed
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
      }  
    }
  }
  else { // TDD
   if (cqi_PMI_ConfigIndex == 0) {        // all UL subframes
     cqirep->Npd = 1;
     cqirep->N_OFFSET_CQI = 0;
   } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period
     cqirep->Npd = 5;
     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-1;
   } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
     cqirep->Npd = 10;
     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-6;
   } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
     cqirep->Npd = 20;
     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-16;
   } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
     cqirep->Npd = 40;
     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-36;
   } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
     cqirep->Npd = 80;
     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-76;
   } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
     cqirep->Npd = 160;
     cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-156;
   }
  }
}

621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
PUCCH_FMT_t get_pucch_format(lte_frame_type_t frame_type,
                             lte_prefix_type_t cyclic_prefix_type,
                             uint8_t SR_payload,
                             uint8_t nb_cw,
                             uint8_t cqi_status,
                             uint8_t ri_status)
{
  if((cqi_status == 0) && (ri_status==0))
  {
      // PUCCH Format 1 1a 1b
      // 1- SR only ==> PUCCH format 1
      // 2- 1bit Ack/Nack with/without SR  ==> PUCCH format 1a
      // 3- 2bits Ack/Nack with/without SR ==> PUCCH format 1b
      if(nb_cw == 1)
      {
          return pucch_format1a;
      }
      if(nb_cw == 2)
      {
          return pucch_format1b;
      }
      if(SR_payload == 1)
      {
Gabriel's avatar
Gabriel committed
644 645
          return pucch_format1;
          /*
646 647 648 649 650 651
          if (frame_type == FDD) {
              return pucch_format1;
          } else if (frame_type == TDD) {
              return pucch_format1b;
          } else {
	      AssertFatal(1==0,"Unknown frame_type");
Gabriel's avatar
Gabriel committed
652
          }*/
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
      }
  }
  else
  {
      // PUCCH Format 2 2a 2b
      // 1- CQI only or RI only  ==> PUCCH format 2
      // 2- CQI or RI + 1bit Ack/Nack for normal CP  ==> PUCCH format 2a
      // 3- CQI or RI + 2bits Ack/Nack for normal CP ==> PUCCH format 2b
      // 4- CQI or RI + Ack/Nack for extended CP ==> PUCCH format 2
      if(nb_cw == 0)
      {
          return pucch_format2;
      }
      if(cyclic_prefix_type == NORMAL)
      {
          if(nb_cw == 1)
          {
              return pucch_format2a;
          }
          if(nb_cw == 2)
          {
              return pucch_format2b;
          }
      }
      else
      {
          return pucch_format2;
      }
  }
Bilel's avatar
Bilel committed
682
  return pucch_format1a;
683
}
684
uint16_t get_n1_pucch(PHY_VARS_UE *ue,
685
		      UE_rxtx_proc_t *proc,
686
                      harq_status_t *harq_ack,
687 688 689 690
                      uint8_t eNB_id,
                      uint8_t *b,
                      uint8_t SR)
{
691

692
  LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
693
  uint8_t nCCE0,nCCE1,nCCE2,nCCE3,harq_ack1,harq_ack0,harq_ack3,harq_ack2;
694
  ANFBmode_t bundling_flag;
Gabriel's avatar
Gabriel committed
695
  uint16_t n1_pucch0=0,n1_pucch1=0,n1_pucch2=0,n1_pucch3=0,n1_pucch_inter;
696 697
  static uint8_t candidate_dl[9]; // which downlink(s) the current ACK/NACK is associating to
  uint8_t last_dl=0xff; // the last downlink with valid DL-DCI. for calculating the PUCCH resource index
698 699
  int sf;
  int M;
700
  uint8_t ack_counter=0;
701
  // clear this, important for case where n1_pucch selection is not used
702
  int subframe=proc->subframe_tx;
703

704
  ue->pucch_sel[subframe] = 0;
705 706 707

  if (frame_parms->frame_type == FDD ) { // FDD
    sf = (subframe<4)? subframe+6 : subframe-4;
Bilel's avatar
Bilel committed
708
    LOG_D(PHY,"n1_pucch_UE: subframe %d, nCCE %d\n",sf,ue->pdcch_vars[proc->subframe_rx&0x1][eNB_id]->nCCE[sf]);
709 710

    if (SR == 0)
Bilel's avatar
Bilel committed
711
      return(frame_parms->pucch_config_common.n1PUCCH_AN + ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[sf]);
712
    else
713
      return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
714
  } else {
715

716
    bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
717
#ifdef DEBUG_PHY_PROC
718 719

    if (bundling_flag==bundling) {
720
      LOG_I(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR,
721
            ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
722
    } else {
723
      LOG_I(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR,
724
            ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
725
    }
726

727
#endif
728

729 730 731 732 733
    switch (frame_parms->tdd_config) {
    case 1:  // DL:S:UL:UL:DL:DL:S:UL:UL:DL

      harq_ack0 = 2; // DTX
      M=1;
734

735
      // This is the offset for a particular subframe (2,3,4) => (0,2,4)
736 737 738
      if (subframe == 2) {  // ACK subframes 5,6
        candidate_dl[0] = 6;
        candidate_dl[1] = 5;
739 740
        M=2;
      } else if (subframe == 3) { // ACK subframe 9
741 742 743 744
        candidate_dl[0] = 9;
      } else if (subframe == 7) { // ACK subframes 0,1
        candidate_dl[0] = 1;
        candidate_dl[1] = 0;
745 746
        M=2;
      } else if (subframe == 8) { // ACK subframes 4
747
        candidate_dl[0] = 4;
748
      } else {
749
        LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal tx-subframe %d for tdd_config %d\n",
750
              ue->Mod_id,proc->frame_tx,subframe,frame_parms->tdd_config);
751
        return(0);
752 753
      }

754 755 756 757 758 759 760 761 762
      // checking which downlink candidate is the last downlink with valid DL-DCI
      int k;
      for (k=0;k<M;k++) {
        if (harq_ack[candidate_dl[k]].send_harq_status>0) {
          last_dl = candidate_dl[k];
          break;
        }
      }
      if (last_dl >= 10) {
763 764
        LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal rx-subframe %d (tx-subframe %d) for tdd_config %d\n",
              ue->Mod_id,proc->frame_tx,last_dl,subframe,frame_parms->tdd_config);
765 766 767 768 769 770 771
        return (0);
      }

      LOG_D(PHY,"SFN/SF %d/%d calculating n1_pucch0 from last_dl=%d\n",
          proc->frame_tx%1024,
          proc->subframe_tx,
          last_dl);
772 773

      // i=0
Bilel's avatar
Bilel committed
774
      nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[last_dl];
775
      n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
776

777
      harq_ack0 = b[0];
778 779

      if (harq_ack0!=2) {  // DTX
780 781 782 783
        if (frame_parms->frame_type == FDD ) {
          if (SR == 0) {  // last paragraph pg 68 from 36.213 (v8.6), m=0
            b[0]=(M==2) ? 1-harq_ack0 : harq_ack0;
            b[1]=harq_ack0;   // in case we use pucch format 1b (subframes 2,7)
784
          ue->pucch_sel[subframe] = 0;
785 786 787
            return(n1_pucch0);
          } else { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213)
            b[0]=harq_ack0;
788
          return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
789 790 791 792 793 794 795 796 797 798 799 800
          }
        } else {
          if (SR == 0) {
            b[0] = harq_ack0;
            b[1] = harq_ack0;
            ue->pucch_sel[subframe] = 0;
            return(n1_pucch0);
          } else {
            b[0] = harq_ack0;
            b[1] = harq_ack0;
            return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
          }
801
        }
802 803 804 805
      }


      break;
806

807 808 809 810 811 812 813
    case 3:  // DL:S:UL:UL:UL:DL:DL:DL:DL:DL
      // in this configuration we have M=2 from pg 68 of 36.213 (v8.6)
      // Note: this doesn't allow using subframe 1 for PDSCH transmission!!! (i.e. SF 1 cannot be acked in SF 2)
      // set ACK/NAKs to DTX
      harq_ack1 = 2; // DTX
      harq_ack0 = 2; // DTX
      // This is the offset for a particular subframe (2,3,4) => (0,2,4)
814
      last_dl = (subframe-2)<<1;
815
      // i=0
Bilel's avatar
Bilel committed
816
      nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[5+last_dl];
817
      n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
818
      // i=1
Bilel's avatar
Bilel committed
819
      nCCE1 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(6+last_dl)%10];
820
      n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
821 822

      // set ACK/NAK to values if not DTX
823 824
      if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(6+last_dl)%10].send_harq_status>0)  // n-6 // subframe 6 is to be ACK/NAKed
        harq_ack1 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(6+last_dl)%10].ack;
825

826 827
      if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[5+last_dl].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
        harq_ack0 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[5+last_dl].ack;
828

829 830 831 832 833
      LOG_D(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d cce1=%d n1_pucch1=%d\n",
                                      proc->frame_tx%1024,
                                      proc->subframe_tx,
                                      nCCE0,n1_pucch0,
                                      nCCE1,n1_pucch1);
834 835

      if (harq_ack1!=2) { // n-6 // subframe 6,8,0 and maybe 5,7,9 is to be ACK/NAKed
836 837 838 839 840 841 842 843 844

        if ((bundling_flag==bundling)&&(SR == 0)) {  // This is for bundling without SR,
          // n1_pucch index takes value of smallest element in set {0,1}
          // i.e. 0 if harq_ack0 is not DTX, otherwise 1
          b[0] = harq_ack1;

          if (harq_ack0!=2)
            b[0]=b[0]&harq_ack0;

845
          ue->pucch_sel[subframe] = 1;
846 847 848 849 850 851 852 853 854 855
          return(n1_pucch1);

        } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1
          if (harq_ack0 == 2)
            harq_ack0 = 0;

          b[1] = harq_ack0;
          b[0] = (harq_ack0!=harq_ack1)?0:1;

          if ((harq_ack0 == 1) && (harq_ack1 == 0)) {
856
            ue->pucch_sel[subframe] = 0;
857 858
            return(n1_pucch0);
          } else {
859
            ue->pucch_sel[subframe] = 1;
860 861 862 863 864 865 866 867 868
            return(n1_pucch1);
          }
        } else if (SR==1) { // SR and 0,1,or 2 ACKS, (first 3 entries in Table 7.3-1 of 36.213)
          // this should be number of ACKs (including
          if (harq_ack0 == 2)
            harq_ack0 = 0;

          b[0]= harq_ack1 | harq_ack0;
          b[1]= harq_ack1 ^ harq_ack0;
869
          return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
870 871 872 873
        }
      } else if (harq_ack0!=2) { // n-7  // subframe 5,7,9 only is to be ACK/NAKed
        if ((bundling_flag==bundling)&&(SR == 0)) {  // last paragraph pg 68 from 36.213 (v8.6), m=0
          b[0]=harq_ack0;
874
          ue->pucch_sel[subframe] = 0;
875 876 877 878
          return(n1_pucch0);
        } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1 with i=1 set to DTX
          b[0] = harq_ack0;
          b[1] = 1-b[0];
879
          ue->pucch_sel[subframe] = 0;
880 881 882 883
          return(n1_pucch0);
        } else if (SR==1) { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213)
          b[0]=harq_ack0;
          b[1]=b[0];
884
          return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
885
        }
886
      }
887

888 889
      break;

890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
    case 4:  // DL:S:UL:UL:DL:DL:DL:DL:DL:DL
          // in this configuration we have M=4 from pg 68 of 36.213 (v8.6)
          // Note: this doesn't allow using subframe 1 for PDSCH transmission!!! (i.e. SF 1 cannot be acked in SF 2)
          // set ACK/NAKs to DTX
          harq_ack3 = 2; // DTX
          harq_ack2 = 2; // DTX
          harq_ack1 = 2; // DTX
          harq_ack0 = 2; // DTX
          // This is the offset for a particular subframe (2,3,4) => (0,2,4)
          //last_dl = (subframe-2)<<1;
          if (subframe == 2) {
          // i=0
          //nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[2+subframe];
          nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(8+subframe)%10];
          n1_pucch0 = 2*get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
          // i=1
          nCCE1 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[2+subframe];
          n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,0) + get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
          // i=2
          nCCE2 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(8+subframe)%10];
          n1_pucch2 = 2*get_Np(frame_parms->N_RB_DL,nCCE2,1) + nCCE2+ frame_parms->pucch_config_common.n1PUCCH_AN;
          // i=3
          //nCCE3 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(9+subframe)%10];
          //n1_pucch3 = get_Np(frame_parms->N_RB_DL,nCCE3,1) + nCCE3 + frame_parms->pucch_config_common.n1PUCCH_AN;

          // set ACK/NAK to values if not DTX
          if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(8+subframe)%10].send_harq_status>0)  // n-6 // subframe 6 is to be ACK/NAKed
            harq_ack0 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(8+subframe)%10].ack;

          if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[2+subframe].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
            harq_ack1 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[2+subframe].ack;

          if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[3+subframe].send_harq_status>0)  // n-6 // subframe 6 is to be ACK/NAKed
            harq_ack2 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[3+subframe].ack;

          //if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(9+subframe)%10].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
            //harq_ack3 = ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(9+subframe)%10].ack;
          //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d cce1=%d n1_pucch1=%d cce2=%d n1_pucch2=%d\n",
          //                      proc->frame_tx%1024,
          //                      proc->subframe_tx,
          //                      nCCE0,n1_pucch0,
          //                      nCCE1,n1_pucch1, nCCE2, n1_pucch2);
          }else if (subframe == 3) {
          // i=0

          nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[4+subframe];