phy_procedures_lte_ue.c 202 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
#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

fnabet's avatar
fnabet committed
76

77 78
extern int oai_exit;

Bilel's avatar
Bilel committed
79
extern double cpuf;
80 81 82



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

87

88

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

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

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

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

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

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

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

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

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

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

170
  int gain_dB = power_dBm - power_max_dBm;
knopp's avatar
knopp committed
171 172 173 174
  int amp_x_100;

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

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

223 224
#endif

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

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

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

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

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

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

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

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

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

Bilel's avatar
Bilel committed
298 299
              }
          }
300

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

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

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

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

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

  int i;

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

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

333
  for (i=0; i<8; i++) {
334 335
    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
336 337
      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;
338
    }
339 340 341 342 343
  }


}

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

knopp's avatar
knopp committed
347
  return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index]);
348 349

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

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


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

}

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

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

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

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

373

374
  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);
375

376 377 378

}

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

382 383
  int subframe=proc->subframe_tx;

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

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

  return(0);
}

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

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

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


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

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

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

484 485
  if (isSubframeSRS) {  
    LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup);
fnabet's avatar
fnabet committed
486 487
      if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup)
      {
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 521
          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
522
                              ue->pdcch_vars[proc->subframe_rx & 0x1][eNB_id]->crnti,
523 524 525 526 527 528 529 530 531
                              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,
532
                      ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack,
Bilel's avatar
Bilel committed
533
                      subframe_tx,proc->subframe_rx,pucch_ack_payload,0) > 0)
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
              {
                  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
555
      }
fnabet's avatar
fnabet committed
556
      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
557 558 559
  }
}

560

knopp's avatar
knopp committed
561 562 563 564 565 566 567 568 569 570 571 572
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;
573
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-2;
knopp's avatar
knopp committed
574 575
    } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
      cqirep->Npd = 10;
576
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-7;
knopp's avatar
knopp committed
577 578
    } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
      cqirep->Npd = 20;
579
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-17;
knopp's avatar
knopp committed
580 581
    } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
      cqirep->Npd = 40;
582
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-37;
knopp's avatar
knopp committed
583 584
    } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
      cqirep->Npd = 80;
585
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-77;
knopp's avatar
knopp committed
586 587
    } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
      cqirep->Npd = 160;
588
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-157;
knopp's avatar
knopp committed
589 590 591 592 593
    }
    else if (cqi_PMI_ConfigIndex > 317) {
      
      if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period
	cqirep->Npd = 32;
594
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-318;
knopp's avatar
knopp committed
595 596 597
      }
      else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period
	cqirep->Npd = 64;
598
	cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-350;
knopp's avatar
knopp committed
599 600 601
      }
      else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period
	cqirep->Npd = 128;
602
	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 631
      }  
    }
  }
  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;
   }
  }
}

632 633 634 635 636
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
637 638
                             uint8_t ri_status,
                             uint8_t bundling_flag)
639 640 641 642 643 644 645
{
  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
646
      if((nb_cw == 1)&&(bundling_flag==bundling))
647 648 649
      {
          return pucch_format1a;
      }
Bilel's avatar
Bilel committed
650 651 652 653
      if((nb_cw == 1)&&(bundling_flag==multiplexing))
      {
          return pucch_format1b;
      }
654 655 656 657 658 659
      if(nb_cw == 2)
      {
          return pucch_format1b;
      }
      if(SR_payload == 1)
      {
Gabriel's avatar
Gabriel committed
660 661
          return pucch_format1;
          /*
662 663 664 665 666 667
          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
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 697
      }
  }
  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
698
  return pucch_format1a;
699
}
700
uint16_t get_n1_pucch(PHY_VARS_UE *ue,
701
		      UE_rxtx_proc_t *proc,
702
                      harq_status_t *harq_ack,
703 704 705 706
                      uint8_t eNB_id,
                      uint8_t *b,
                      uint8_t SR)
{
707

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

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

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

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

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

    if (bundling_flag==bundling) {
Gabriel's avatar
Gabriel committed
736
      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,
737
            ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
738
    } else {
Gabriel's avatar
Gabriel committed
739
      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,
740
            ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
741
    }
742

743
#endif
744

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

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

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

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

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

793
      harq_ack0 = b[0];
794 795

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


      break;
822

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

      // set ACK/NAK to values if not DTX
839 840
      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;
841

842 843
      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;
844

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

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

        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;

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

904 905
      break;

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

934 935
          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;
936

937 938
          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;
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

          //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,
984 985 986 987 988 989 990 991
             b[0] = 1;
             ack_counter = 0;

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

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

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

Gabriel's avatar
Gabriel committed
1017
             //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch n1_pucch_inter=%d  b[0]=%d b[1]=%d \n",
1018 1019
             //                                           proc->frame_tx%1024,
             //                                           proc->subframe_tx,n1_pucch_inter,
Gabriel's avatar
Gabriel committed
1020
             //                                           b[0],b[1]);
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 1027
                
             if (subframe == 3) {
                 LOG_I(PHY, "sbuframe=%d \n",subframe);
1028 1029
              if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) {
                b[0] = 1;
Bilel's avatar
Bilel committed
1030
                b[1] = 1;
1031 1032 1033 1034 1035 1036 1037
                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
1038
                b[1] = 1;
1039 1040
                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
1041 1042
                b[0] = 1;
                b[1] = 0;
1043 1044
                return(n1_pucch1);
              } else if ((harq_ack0 == 0) && (harq_ack1 == 2) && (harq_ack2 == 2) && (harq_ack3 == 2)) {
Bilel's avatar
Bilel committed
1045 1046
                b[0] = 1;
                b[1] = 0;
1047 1048
                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
1049 1050
                b[0] = 1;
                b[1] = 0;
1051 1052 1053 1054 1055 1056 1057
                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
1058
                b[1] = 1;
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 1104
                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
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
             } else if (subframe == 2) {
                if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1)) {
                 b[0] = 1;
                 b[1] = 1;
                 return(n1_pucch2);
               } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0))) {
                 b[0] = 1;
                 b[1] = 1;
                 return(n1_pucch1);
               } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1)) {
                 b[0] = 1;
                 b[1] = 1;
                 return(n1_pucch0);
               } else if ((harq_ack0 == 1) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0))) {
                 b[0] = 0;
                 b[1] = 1;
                 return(n1_pucch0);
               } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && (harq_ack1 == 1) && (harq_ack2 == 1)) {
                 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))) {
                 b[1] = 0;
                 b[0] = 0;
                 return(n1_pucch1);
               } else if (((harq_ack0 == 2) || (harq_ack0 == 0)) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && (harq_ack2 == 1)) {
                 b[0] = 0;
                 b[1] = 0;
                 return(n1_pucch2);
               } else if ((harq_ack0 == 2) && (harq_ack1 == 2) && (harq_ack2 == 0)) {
                 b[0] = 0;
                 b[1] = 1;
                 return(n1_pucch2);
               } else if ((harq_ack0 == 2) && (harq_ack1 == 0) && ((harq_ack2 == 2) || (harq_ack2 == 0))) {
                 b[0] = 1;
                 b[1] = 0;
                 return(n1_pucch1);
               } else if ((harq_ack0 == 0) && ((harq_ack1 == 2) || (harq_ack1 == 0)) && ((harq_ack2 == 2) || (harq_ack2 == 0))) {
                 b[0] = 1;
                 b[1] = 0;
                 return(n1_pucch0);
               }
1147

Bilel's avatar
Bilel committed
1148
             }
1149 1150
            } 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
1151
              ack_counter = 0;
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
              if (harq_ack0==1)
                 ack_counter ++;
              if (harq_ack1==1)
                 ack_counter ++;
              if (harq_ack2==1)
                 ack_counter ++;
              if (harq_ack3==1)
                 ack_counter ++;

            switch (ack_counter) {
               case 0:
                 b[0] = 0;
                 b[1] = 0;
               break;

               case 1:
                 b[0] = 1;
                 b[1] = 1;
               break;

               case 2:
                 b[0] = 1;
                 b[1] = 0;
               break;

               case 3:
                 b[0] = 0;
                 b[1] = 1;
               break;

               case 4:
                 b[0] = 1;
                 b[1] = 1;
               break;
            }

            ack_counter = 0;
            return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
          }

          break;

1194
    }  // switch tdd_config
1195
  }
1196

Cedric Roux's avatar
Cedric Roux committed
1197
  LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, exit without proper return\n", ue->Mod_id, proc->frame_tx);
1198 1199 1200 1201 1202 1203
  return(-1);
}


#ifdef EMOS
/*
1204
  void phy_procedures_emos_UE_TX(uint8_t next_slot,uint8_t eNB_id) {
1205
  uint8_t harq_pid;
1206

1207 1208

  if (next_slot%2==0) {
1209 1210 1211 1212 1213 1214 1215
  // get harq_pid from subframe relationship
  harq_pid = subframe2harq_pid(&ue->frame_parms,ue->frame,(next_slot>>1));
  if (harq_pid==255) {
  LOG_E(PHY,"[UE%d] Frame %d : FATAL ERROR: illegal harq_pid, returning\n",
  0,ue->frame);
  return;
  }
1216

1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
  if (ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) {
  emos_dump_UE.uci_cnt[next_slot>>1] = 1;
  memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o,ulsch[eNB_id]->o,MAX_CQI_BITS*sizeof(char));
  emos_dump_UE.UCI_data[0][next_slot>>1].O = ulsch[eNB_id]->O;
  memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_RI,ulsch[eNB_id]->o_RI,2*sizeof(char));
  emos_dump_UE.UCI_data[0][next_slot>>1].O_RI = ulsch[eNB_id]->O_RI;
  memcpy(emos_dump_UE.UCI_data[0][next_slot>>1].o_ACK,ulsch[eNB_id]->o_ACK,4*sizeof(char));
  emos_dump_UE.UCI_data[0][next_slot>>1].O_ACK = ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK;
  }
  else {
  emos_dump_UE.uci_cnt[next_slot>>1] = 0;
  }
  }
1230 1231 1232 1233
  }
*/
#endif

Bilel's avatar
Bilel committed
1234
void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empty_subframe) {
1235

1236
  int aa;
1237
  LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
1238

1239 1240 1241 1242
  int nsymb;
  int subframe_tx = proc->subframe_tx;
  int frame_tx = proc->frame_tx;
  int ulsch_start;
1243
  int overflow=0;
1244
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
1245
  int k,l;
1246
  int dummy_tx_buffer[frame_parms->samples_per_tti] __attribute__((aligned(16)));
1247 1248
#endif

1249
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN);
Gabriel's avatar
Gabriel committed
1250
#if UE_TIMING_TRACE
1251
  start_meas(&ue->ofdm_mod_stats);
Gabriel's avatar
Gabriel committed
1252
#endif
1253 1254 1255 1256
  nsymb = (frame_parms->Ncp == 0) ? 14 : 12;
  
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case
  ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti-
Gabriel's avatar
Gabriel committed
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
         ue->hw_timing_advance-
         ue->timing_advance-
         ue->N_TA_offset+5);
  //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);

  if(ulsch_start < 0)
      ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);

  if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti))
      ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);

  //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);
1269 1270 1271
#else //this is the normal case
  ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance;
#endif //else EXMIMO
Bilel's avatar
Bilel committed
1272

1273
//#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
Bilel's avatar
Bilel committed
1274 1275 1276 1277 1278 1279
  if (empty_subframe)
  {
//#if 1
      overflow = ulsch_start - 9*frame_parms->samples_per_tti;
      for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {

1280 1281 1282 1283 1284 1285 1286 1287 1288
          if (overflow > 0)
		 {
			 memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*(frame_parms->samples_per_tti-overflow));
			 memset(&ue->common_vars.txdata[aa][0