phy_procedures_lte_ue.c 176 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 40 41 42 43
#include "defs.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"

#ifdef EMOS
#include "SCHED/phy_procedures_emos.h"
#endif

Florian Kaltenberger's avatar
Florian Kaltenberger committed
44
#define DEBUG_PHY_PROC
45 46 47 48 49 50 51 52 53 54 55 56 57 58

#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"
59
#include "UTIL/OPT/opt.h"
60

61 62 63 64
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

65 66 67
#include "PHY/defs.h"

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

69 70
#include "T.h"

71 72 73 74 75 76 77
#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
78
extern double cpuf;
79 80 81



82
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
83
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
84 85
#endif

86

87

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

  coded_bits_per_codeword = get_G(&ue->frame_parms,
Bilel's avatar
Bilel committed
94 95 96 97
                                  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
98
                                  ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
99
                                  proc->frame_rx,
100 101
          subframe,
          ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]);
102

103 104 105
  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);
106
  /*
107 108 109 110
    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);
111
  */
112 113
  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);
114

115 116
  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);
117 118
}

119
void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe)
120
{
121
  unsigned int coded_bits_per_codeword;
122
  uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12);
123

124 125 126
  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,
127
                                  2,
128
                                  1,
Bilel's avatar
Bilel committed
129
                                  ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
130
                                  proc->frame_rx,
131 132
          subframe,
          0);
133
  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",
134
        ue->Mod_id,
135 136
  ue->frame_parms.ofdm_symbol_size,
  nsymb,
137 138 139
        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
140
        ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
141
        coded_bits_per_codeword);
142

143
  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);
144

145
  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);
146 147
  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);
148
  /*
149 150 151 152
    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);
153
  */
154 155
  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);
156

157 158
  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);
159
  sleep(1);
160 161 162
  exit(-1);
}

163
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
164 165
//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};
/*
166 167
  unsigned int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL)
  {
168

169
  int gain_dB = power_dBm - power_max_dBm;
170 171 172 173
  int amp_x_100;

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

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);
  if ((nb_rb >0) && (nb_rb <= N_RB_UL)) {
    return((int)(AMP*sqrt(gain_lin*N_RB_UL/(double)nb_rb)));
  }
  else {
    LOG_E(PHY,"Illegal nb_rb/N_RB_UL combination (%d/%d)\n",nb_rb,N_RB_UL);
    mac_xface->macphy_exit("");
  }
  return(0);
}

222 223
#endif

224
void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe)
225
{
226
  unsigned int coded_bits_per_codeword;
227
  uint8_t nsymb = ((ue->frame_parms.Ncp == 0) ? 14 : 12);
228

229 230 231
  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,
232
                                  2,
233
                                  1,
Bilel's avatar
Bilel committed
234
                                  ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
235
                                  proc->frame_rx,
236 237
          subframe,
          0);
238
  LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n",
239 240 241 242
        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
243
        ue->pdcch_vars[0&0x1][eNB_id]->num_pdcch_symbols,
244
        coded_bits_per_codeword);
245

246
  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);
247 248
  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);
249
  /*
250 251 252 253
    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);
254
  */
255 256
  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);
257

258 259
  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);
260
}
261

262 263
void phy_reset_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
264 265 266

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

268
  uint8_t i,j,k,s;
269
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
270

Bilel's avatar
Bilel committed
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
  //[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;
                      }
                  }
              }
288
          }
289

Bilel's avatar
Bilel committed
290 291 292 293 294 295
          //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;
296

Bilel's avatar
Bilel committed
297 298
              }
          }
299

Bilel's avatar
Bilel committed
300 301
          // flush Msg3 buffer
          ue->ulsch_Msg3_active[i] = 0;
302

Bilel's avatar
Bilel committed
303
      }
304 305 306
  }
}

307 308
void ra_failed(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
309 310

  // if contention resolution fails, go back to PRACH
311
  PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PRACH;
Bilel's avatar
Bilel committed
312 313 314 315
  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;
316
  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);
317 318 319
  //mac_xface->macphy_exit("");
}

320 321
void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
322 323 324

  int i;

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

Bilel's avatar
Bilel committed
327 328
  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;
329
  PHY_vars_UE_g[Mod_id][CC_id]->ulsch_Msg3_active[eNB_index] = 0;
330
  PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PUSCH;
331

332
  for (i=0; i<8; i++) {
333 334
    if (PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]) {
      PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->status=IDLE;
Bilel's avatar
Bilel committed
335 336
      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;
337
    }
338 339 340 341 342
  }


}

343 344
UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
{
345

346
  return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index]);
347 348

}
349
void process_timing_advance_rar(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint16_t timing_advance) {
350

351
  ue->timing_advance = timing_advance*4;
352 353


354
#ifdef DEBUG_PHY_PROC
Cedric Roux's avatar
Cedric Roux committed
355 356 357
  /* 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);
358 359 360 361
#endif

}

362 363
void process_timing_advance(uint8_t Mod_id,uint8_t CC_id,int16_t timing_advance)
{
364

365
  //  uint32_t frame = PHY_vars_UE_g[Mod_id]->frame;
366

367
  // timing advance has Q1.5 format
368
  timing_advance = timing_advance - 31;
369

370 371
  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!!!

372

Bilel's avatar
Bilel committed
373
  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);
374

375 376 377

}

378
uint8_t is_SR_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id)
379 380
{

381 382
  int subframe=proc->subframe_tx;

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

387 388
  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)
389
      return(1);
390 391
  } 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))
392
      return(1);
393
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 34) { // 20 ms SR period
394
    if ((10*(proc->frame_tx&1)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15))
395
      return(1);
396
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 74) { // 40 ms SR period
397
    if ((10*(proc->frame_tx&3)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35))
398
      return(1);
399
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 154) { // 80 ms SR period
400
    if ((10*(proc->frame_tx&7)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75))
401 402 403 404 405 406
      return(1);
  }

  return(0);
}

407 408 409 410 411 412 413 414 415 416 417
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));

418 419 420
  if (cqirep->cqi_PMI_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI)
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
    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));
439 440 441
  if (cqirep->ri_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0)
442 443 444 445 446
    return(1);
  else
    return(0);
}

Bilel's avatar
Bilel committed
447 448 449 450 451 452 453 454 455
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)
{
456 457
    //PHY_MEASUREMENTS *meas = &ue->measurements;
    //uint8_t transmission_mode = ue->transmission_mode[eNB_id];
Bilel's avatar
Bilel committed
458 459


460
    //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
461 462 463 464 465
    if (cqi_status == 1 || ri_status == 1)
    {
        ulsch->O = 4;
    }
}
Bilel's avatar
Bilel committed
466

467
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
468
{
469

470 471 472 473 474 475 476 477
  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
478 479 480

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

483
  if (isSubframeSRS) {
484
    LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup);
fnabet's avatar
fnabet committed
485 486
      if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup)
      {
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
          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;
                      SR_payload = mac_xface->ue_get_SR(Mod_id,
                              CC_id,
                              frame_tx,
                              eNB_id,
Bilel's avatar
Bilel committed
521
                              ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->crnti,
522 523 524 525 526 527 528 529 530
                              subframe_tx); // subframe used for meas gap

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

              uint8_t pucch_ack_payload[2];
              if (get_ack(&ue->frame_parms,
Bilel's avatar
Bilel committed
531
                      ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack,
Bilel's avatar
Bilel committed
532
                      subframe_tx,proc->subframe_rx,pucch_ack_payload,0) > 0)
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
              {
                  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
554
      }
fnabet's avatar
fnabet committed
555
      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
556 557 558
  }
}

559

knopp's avatar
knopp committed
560 561 562 563 564 565 566 567 568 569 570 571
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;
572
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-2;
knopp's avatar
knopp committed
573 574
    } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
      cqirep->Npd = 10;
575
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-7;
knopp's avatar
knopp committed
576 577
    } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
      cqirep->Npd = 20;
578
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-17;
knopp's avatar
knopp committed
579 580
    } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
      cqirep->Npd = 40;
581
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-37;
knopp's avatar
knopp committed
582 583
    } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
      cqirep->Npd = 80;
584
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-77;
knopp's avatar
knopp committed
585 586
    } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
      cqirep->Npd = 160;
587
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-157;
knopp's avatar
knopp committed
588 589
    }
    else if (cqi_PMI_ConfigIndex > 317) {
590

knopp's avatar
knopp committed
591
      if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period
592
  cqirep->Npd = 32;
593
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-318;
knopp's avatar
knopp committed
594 595
      }
      else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period
596 597
  cqirep->Npd = 64;
  cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-350;
knopp's avatar
knopp committed
598 599
      }
      else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period
600 601 602
  cqirep->Npd = 128;
  cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-414;
      }
knopp's avatar
knopp committed
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
    }
  }
  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;
   }
  }
}

631 632 633 634 635
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,
Bilel's avatar
Bilel committed
636 637
                             uint8_t ri_status,
                             uint8_t bundling_flag)
638 639 640 641 642 643 644
{
  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
Bilel's avatar
Bilel committed
645
      if((nb_cw == 1)&&(bundling_flag==bundling))
646 647 648
      {
          return pucch_format1a;
      }
Bilel's avatar
Bilel committed
649 650 651 652
      if((nb_cw == 1)&&(bundling_flag==multiplexing))
      {
          return pucch_format1b;
      }
653 654 655 656 657 658 659
      if(nb_cw == 2)
      {
          return pucch_format1b;
      }
      if(SR_payload == 1)
      {
          return pucch_format1;
Gabriel's avatar
Gabriel committed
660
          /*
661 662 663 664 665
          if (frame_type == FDD) {
              return pucch_format1;
          } else if (frame_type == TDD) {
              return pucch_format1b;
          } else {
666
              AssertFatal(1==0,"Unknown frame_type");
Gabriel's avatar
Gabriel committed
667
          }*/
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
      }
  }
  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
697
  return pucch_format1a;
698
}
699
uint16_t get_n1_pucch(PHY_VARS_UE *ue,
700
          UE_rxtx_proc_t *proc,
701
                      harq_status_t *harq_ack,
702 703 704 705
                      uint8_t eNB_id,
                      uint8_t *b,
                      uint8_t SR)
{
706

707
  LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
708
  uint8_t nCCE0,nCCE1,nCCE2,nCCE3,harq_ack1,harq_ack0,harq_ack3,harq_ack2;
709
  ANFBmode_t bundling_flag;
Gabriel's avatar
Gabriel committed
710
  uint16_t n1_pucch0=0,n1_pucch1=0,n1_pucch2=0,n1_pucch3=0,n1_pucch_inter;
711 712
  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
713 714
  int sf;
  int M;
715
  uint8_t ack_counter=0;
716
  // clear this, important for case where n1_pucch selection is not used
717
  int subframe=proc->subframe_tx;
718

719
  ue->pucch_sel[subframe] = 0;
720 721 722

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

    if (SR == 0)
Bilel's avatar
Bilel committed
726
      return(frame_parms->pucch_config_common.n1PUCCH_AN + ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[sf]);
727
    else
728
      return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
729
  } else {
730

731
    bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
732
#ifdef DEBUG_PHY_PROC
733 734

    if (bundling_flag==bundling) {
Gabriel's avatar
Gabriel committed
735
      LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, bundling, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR,
736
            ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
737
    } else {
Gabriel's avatar
Gabriel committed
738
      LOG_D(PHY,"[UE%d] Frame %d subframe %d : get_n1_pucch, multiplexing, SR %d/%d\n",ue->Mod_id,proc->frame_tx,subframe,SR,
739
            ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
740
    }
741

742
#endif
743

744 745 746 747 748
    switch (frame_parms->tdd_config) {
    case 1:  // DL:S:UL:UL:DL:DL:S:UL:UL:DL

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

750
      // This is the offset for a particular subframe (2,3,4) => (0,2,4)
751 752 753
      if (subframe == 2) {  // ACK subframes 5,6
        candidate_dl[0] = 6;
        candidate_dl[1] = 5;
754 755
        M=2;
      } else if (subframe == 3) { // ACK subframe 9
756 757 758 759
        candidate_dl[0] = 9;
      } else if (subframe == 7) { // ACK subframes 0,1
        candidate_dl[0] = 1;
        candidate_dl[1] = 0;
760 761
        M=2;
      } else if (subframe == 8) { // ACK subframes 4
762
        candidate_dl[0] = 4;
763
      } else {
764
        LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal tx-subframe %d for tdd_config %d\n",
765
              ue->Mod_id,proc->frame_tx,subframe,frame_parms->tdd_config);
766
        return(0);
767 768
      }

769 770 771 772 773 774 775 776 777
      // 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) {
778 779
        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);
780 781 782 783 784 785 786
        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);
787 788

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

792
      harq_ack0 = b[0];
793 794

      if (harq_ack0!=2) {  // DTX
795 796 797 798
        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)
799
          ue->pucch_sel[subframe] = 0;
800 801 802
            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;
803
          return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
804 805 806 807 808 809 810 811 812 813 814 815
          }
        } 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);
          }
816
        }
817 818 819 820
      }


      break;
821

822 823 824 825 826 827 828
    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)
829
      last_dl = (subframe-2)<<1;
830
      // i=0
Bilel's avatar
Bilel committed
831
      nCCE0 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[5+last_dl];
832
      n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
833
      // i=1
Bilel's avatar
Bilel committed
834
      nCCE1 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(6+last_dl)%10];
835
      n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
836 837

      // set ACK/NAK to values if not DTX
Bilel's avatar
Bilel committed
838 839
      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;
840

Bilel's avatar
Bilel committed
841 842
      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;
843

844 845 846 847 848
      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);
849 850

      if (harq_ack1!=2) { // n-6 // subframe 6,8,0 and maybe 5,7,9 is to be ACK/NAKed
851 852 853 854 855 856 857 858 859

        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;

860
          ue->pucch_sel[subframe] = 1;
861 862 863 864 865 866 867 868 869 870
          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)) {
871
            ue->pucch_sel[subframe] = 0;
872 873
            return(n1_pucch0);
          } else {
874
            ue->pucch_sel[subframe] = 1;
875 876 877 878 879 880 881 882 883
            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;
884
          return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
885 886 887 888
        }
      } 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;
889
          ue->pucch_sel[subframe] = 0;
890 891 892 893
          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];
894
          ue->pucch_sel[subframe] = 0;
895 896 897 898
          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];
899
          return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
900
        }
901
      }
902

903 904
      break;

905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
    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[(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
920
          nCCE1 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[3+subframe];
921 922
          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
923
          nCCE2 = ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->nCCE[(2+subframe)%10];
924 925 926 927 928 929 930 931 932
          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;

933 934
          if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[3+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[3+subframe].ack;
935

936 937
          if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(2+subframe)%10].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[(2+subframe)%10].ack;
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

          //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];
          n1_pucch0 = 3*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[5+subframe];
          n1_pucch1 = 2*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[(6+subframe)];
          n1_pucch2 = get_Np(frame_parms->N_RB_DL,nCCE2,0) + 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[(3+subframe)];
          n1_pucch3 = 3*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[4+subframe].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[4+subframe].ack;

          if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[5+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[5+subframe].ack;

          if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(6+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[(6+subframe)].ack;

          if (ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack[(3+subframe)].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[(3+subframe)].ack;
          }

          //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch cce0=%d n1_pucch0=%d harq_ack0=%d cce1=%d n1_pucch1=%d harq_ack1=%d cce2=%d n1_pucch2=%d harq_ack2=%d cce3=%d n1_pucch3=%d harq_ack3=%d bundling_flag=%d\n",
          //                                proc->frame_tx%1024,
          //                                proc->subframe_tx,
          //                                nCCE0,n1_pucch0,harq_ack0,
          //                                nCCE1,n1_pucch1,harq_ack1, nCCE2, n1_pucch2, harq_ack2,
          //                                nCCE3, n1_pucch3, harq_ack3, bundling_flag);

          if ((bundling_flag==bundling)&&(SR == 0)) {  // This is for bundling without SR,
983 984 985 986 987 988 989 990
             b[0] = 1;
             ack_counter = 0;

             if ((harq_ack3!=2) ) {
                b[0] = b[0]&harq_ack3;
                n1_pucch_inter = n1_pucch3;
                ack_counter ++;
             }
991
             if ((harq_ack0!=2) ) {
992
                b[0] = b[0]&harq_ack0;
993
                n1_pucch_inter = n1_pucch0;
994
                ack_counter ++;
995 996 997 998
             }
             if ((harq_ack1!=2) ) {
                b[0] = b[0]&harq_ack1;
                n1_pucch_inter = n1_pucch1;
999
                ack_counter ++;
1000 1001 1002 1003
             }
             if ((harq_ack2!=2) ) {
                b[0] = b[0]&harq_ack2;
                n1_pucch_inter = n1_pucch2;
1004
                ack_counter ++;
1005 1006
             }

1007 1008 1009 1010
             if (ack_counter == 0)
                 b[0] = 0;

             /*if (subframe == 3) {
1011 1012
                n1_pucch_inter = n1_pucch2;
             } else if (subframe == 2) {
1013 1014
                n1_pucch_inter = n1_pucch1;
             }*/
1015

Gabriel's avatar
Gabriel committed
1016
             //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch n1_pucch_inter=%d  b[0]=%d b[1]=%d \n",
1017 1018
             //                                           proc->frame_tx%1024,
             //                                           proc->subframe_tx,n1_pucch_inter,
Gabriel's avatar
Gabriel committed
1019
             //                                           b[0],b[1]);
1020 1021 1022 1023 1024

              return(n1_pucch_inter);

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

Bilel's avatar
Bilel committed
1025 1026
             if (subframe == 3) {
                 LOG_I(PHY, "sbuframe=%d \n",subframe);
1027 1028
              if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) {
                b[0] = 1;
Bilel's avatar
Bilel committed
1029
                b[1] = 1;
1030 1031 1032 1033 1034 1035 1036
                return(n1_pucch1);
              } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) {
                b[0] = 1;
                b[1] = 0;
                return(n1_pucch1);
              } else if (((harq_ack0 == 0) || (harq_ack0 == 2)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 0) && (harq_ack3 == 2)) {
                b[0] = 1;
Bilel's avatar
Bilel committed
1037
                b[1] = 1;
1038 1039
                return(n1_pucch2);
              } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) {
Bilel's avatar
Bilel committed
1040 1041
                b[0] = 1;
                b[1] = 0;
1042 1043
                return(n1_pucch1);
              } else if ((harq_ack0 == 0) && (harq_ack1 == 2) && (harq_ack2 == 2) && (harq_ack3 == 2)) {
Bilel's avatar
Bilel committed
1044 1045
                b[0] = 1;
                b[1] = 0;
1046 1047
                return(n1_pucch0);
              } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) {
Bilel's avatar
Bilel committed
1048 1049
                b[0] = 1;
                b[1] = 0;
1050 1051 1052 1053 1054 1055 1056
                return(n1_pucch1);
              } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && (harq_ack3 == 1)) {
                b[0] = 0;
                b[1] = 1;
                return(n1_pucch3);
              } else if (((harq_ack0 == 0) || (harq_ack0 == 2)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 0)) {
                b[0] = 1;
Bilel's avatar
Bilel committed
1057
                b[1] = 1;
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 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
                return(n1_pucch3);
              } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) {
                b[0] = 0;
                b[1] = 1;
                return(n1_pucch2);
              } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) {
                b[0] = 0;
                b[1] = 1;
                return(n1_pucch0);
              } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) {
                b[0] = 0;
                b[1] = 1;
                return(n1_pucch0);
              } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) {
                b[0] = 0;
                b[1] = 1;
                return(n1_pucch3);
              } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 0) && (harq_ack2 == 2) && (harq_ack3 == 2)) {
                b[0] = 0;
                b[1] = 0;
                return(n1_pucch1);
              } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) {
                b[0] = 1;
                b[1] = 0;
                return(n1_pucch2);
              } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) {
                b[0] = 1;
                b[1] = 0;
                return(n1_pucch3);
              } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) {
                b[0] = 0;
                b[1] = 1;
                return(n1_pucch1);
              } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && (harq_ack3 == 1)) {
                b[0] = 0;
                b[1] = 1;
                return(n1_pucch3);
              } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1) && ((harq_ack3 == 2) || (harq_ack3 == 0))) {
                b[0] = 0;
                b[1] = 0;
                return(n1_pucch2);
              } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack3 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0))) {
                b[0] = 0;
                b[1] = 0;
                return(n1_pucch3);
                }
Bilel's avatar
Bilel committed
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
             } else if (subframe == 2) {
                if ((harq_ack0 ==