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

35
#include "assertions.h"
36 37
#include "PHY/defs_UE.h"
#include "PHY/phy_extern_ue.h"
38 39
#include <sched.h>
#include "targets/RT/USER/lte-softmodem.h"
40

41 42
#include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h"
#include "SCHED_UE/sched_UE.h"
knopp's avatar
knopp committed
43 44 45
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"

46 47

#ifndef PUCCH
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
48
  #define PUCCH
49 50
#endif

51
#include "LAYER2/MAC/mac.h"
52
#include "common/utils/LOG/log.h"
53

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

57
#if defined(ENABLE_ITTI)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
58
  #include "intertask_interface.h"
59 60
#endif

61
#include "PHY/defs_UE.h"
62

63
#include "PHY/CODING/coding_extern.h"
64

65 66
#include "T.h"

67
#include "PHY/TOOLS/tools_defs.h"
68

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

#define NS_PER_SLOT 500000

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

76 77
void Msg1_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id);
void Msg3_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id);
78

79
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
80
  extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
81 82
#endif

83 84 85 86 87
void get_dumpparam(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id, uint8_t nb_rb,
                   uint32_t *alloc_even, uint8_t subframe,uint32_t Qm, uint32_t Nl, uint32_t tm,
                   uint8_t *nsymb, uint32_t *coded_bits_per_codeword) {
  *nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12;
  *coded_bits_per_codeword = get_G(&ue->frame_parms,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
88 89 90 91 92 93 94 95
                                   nb_rb,
                                   alloc_even,
                                   Qm,
                                   Nl,
                                   ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols,
                                   proc->frame_rx,
                                   subframe,
                                   tm);
96
}
97

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
98 99
void dump_dlsch(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid) {
  if (LOG_DUMPFLAG(DEBUG_UE_PHYPROC)) {
100 101
    unsigned int coded_bits_per_codeword;
    uint8_t nsymb ;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
102 103 104 105 106 107 108 109
    get_dumpparam(ue, proc, eNB_id,
                  ue->dlsch[ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->nb_rb,
                  ue->dlsch[ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->rb_alloc_even,
                  subframe,
                  ue->dlsch[ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->Qm,
                  ue->dlsch[ue->current_thread_id[subframe]][eNB_id][0]->harq_processes[harq_pid]->Nl,
                  ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id],
                  &nsymb, &coded_bits_per_codeword);
110 111 112 113 114 115 116 117 118 119 120 121 122
    LOG_M("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,2,1);
    LOG_M("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars[ue->current_thread_id[subframe]][0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
    LOG_M("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars[ue->current_thread_id[subframe]][0]->dl_ch_estimates_ext[0],300*nsymb,1,1);
    /*
      LOG_M("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1);
      LOG_M("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1);
      LOG_M("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1);
      LOG_M("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1);
    */
    LOG_M("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars[ue->current_thread_id[subframe]][0]->rxdataF_comp0[0],300*12,1,1);
    LOG_M("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars[ue->current_thread_id[subframe]][0]->llr[0],coded_bits_per_codeword,1,0);
    LOG_M("dlsch_mag1.m","dlschmag1",ue->pdsch_vars[ue->current_thread_id[subframe]][0]->dl_ch_mag0,300*12,1,1);
    LOG_M("dlsch_mag2.m","dlschmag2",ue->pdsch_vars[ue->current_thread_id[subframe]][0]->dl_ch_magb0,300*12,1,1);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
123
  }
124 125
}

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
126 127
void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe) {
  if (LOG_DUMPFLAG(DEBUG_UE_PHYPROC)) {
128 129 130
    unsigned int coded_bits_per_codeword;
    uint8_t nsymb;
    get_dumpparam(ue, proc, eNB_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
131 132 133 134
                  ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb,
                  ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even,
                  subframe,2,1,0,
                  &nsymb, &coded_bits_per_codeword);
135
    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",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
136 137 138 139 140 141 142 143
          ue->Mod_id,
          ue->frame_parms.ofdm_symbol_size,
          nsymb,
          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,
          ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols,
          coded_bits_per_codeword);
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    LOG_M("rxsig0.m","rxs0", &ue->common_vars.rxdata[0][subframe*ue->frame_parms.samples_per_tti],ue->frame_parms.samples_per_tti,1,1);
    LOG_M("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[0],nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
    LOG_M("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_SI[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
    LOG_M("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);
    /*
      LOG_M("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1);
      LOG_M("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1);
      LOG_M("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1);
      LOG_M("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1);
    */
    LOG_M("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);
    LOG_M("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_SI[0]->llr[0],coded_bits_per_codeword,1,0);
    LOG_M("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_SI[0]->dl_ch_mag0,300*nsymb,1,1);
    LOG_M("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_SI[0]->dl_ch_magb0,300*nsymb,1,1);
    sleep(1);
    exit(-1);
  }
161 162
}

163
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
knopp's avatar
knopp committed
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;
knopp's avatar
knopp committed
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;
knopp's avatar
knopp committed
176
  case 15:
177 178
  amp_x_100 = 158*AMP;  // 158 = 100*sqrt(15/6)
  break;
knopp's avatar
knopp committed
179
  case 25:
180 181
  amp_x_100 = 204*AMP;  // 204 = 100*sqrt(25/6)
  break;
knopp's avatar
knopp committed
182
  case 50:
183 184
  amp_x_100 = 286*AMP;  // 286 = 100*sqrt(50/6)
  break;
knopp's avatar
knopp committed
185
  case 75:
186 187
  amp_x_100 = 354*AMP;  // 354 = 100*sqrt(75/6)
  break;
knopp's avatar
knopp committed
188
  case 100:
189 190
  amp_x_100 = 408*AMP;  // 408 = 100*sqrt(100/6)
  break;
knopp's avatar
knopp committed
191
  default:
192 193 194
  LOG_E(PHY,"Unknown PRB size %d\n",N_RB_UL);
  mac_xface->macphy_exit("");
  break;
knopp's avatar
knopp committed
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)
  }
knopp's avatar
knopp committed
203 204
*/

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
205
unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb) {
206
  int gain_dB;
knopp's avatar
knopp committed
207 208
  double gain_lin;

209 210 211 212 213
  if (power_dBm<=power_max_dBm)
    gain_dB = power_dBm - power_max_dBm;
  else
    gain_dB = 0;

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

219 220
#endif

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
221 222
void dump_dlsch_ra(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe) {
  if (LOG_DUMPFLAG(DEBUG_UE_PHYPROC)) {
223 224 225
    unsigned int coded_bits_per_codeword;
    uint8_t nsymb ;
    get_dumpparam(ue, proc, eNB_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
226 227 228 229
                  ue->dlsch_SI[eNB_id]->harq_processes[0]->nb_rb,
                  ue->dlsch_SI[eNB_id]->harq_processes[0]->rb_alloc_even,
                  subframe,2,1,0,
                  &nsymb, &coded_bits_per_codeword);
230
    LOG_D(PHY,"[UE %d] Dumping dlsch_ra : nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
231 232 233 234 235 236
          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,
          ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols,
          coded_bits_per_codeword);
237 238 239 240 241 242 243 244 245 246 247 248 249 250
    LOG_M("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[0],2*12*ue->frame_parms.ofdm_symbol_size,2,1);
    LOG_M("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_ra[0]->rxdataF_ext[0],2*12*ue->frame_parms.ofdm_symbol_size,1,1);
    LOG_M("dlsch00_ch0_ext.m","dl00_ch0_ext", ue->pdsch_vars_ra[0]->dl_ch_estimates_ext[0],300*nsymb,1,1);
    /*
      LOG_M("dlsch01_ch0_ext.m","dl01_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[1],300*12,1,1);
      LOG_M("dlsch10_ch0_ext.m","dl10_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[2],300*12,1,1);
      LOG_M("dlsch11_ch0_ext.m","dl11_ch0_ext",pdsch_vars[0]->dl_ch_estimates_ext[3],300*12,1,1);
      LOG_M("dlsch_rho.m","dl_rho",pdsch_vars[0]->rho[0],300*12,1,1);
    */
    LOG_M("dlsch_rxF_comp0.m","dlsch0_rxF_comp0", ue->pdsch_vars_ra[0]->rxdataF_comp0[0],300*nsymb,1,1);
    LOG_M("dlsch_rxF_llr.m","dlsch_llr", ue->pdsch_vars_ra[0]->llr[0],coded_bits_per_codeword,1,0);
    LOG_M("dlsch_mag1.m","dlschmag1",ue->pdsch_vars_ra[0]->dl_ch_mag0,300*nsymb,1,1);
    LOG_M("dlsch_mag2.m","dlschmag2",ue->pdsch_vars_ra[0]->dl_ch_magb0,300*nsymb,1,1);
  }
251
}
252

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
253
void phy_reset_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index) {
254 255
  // This flushes ALL DLSCH and ULSCH harq buffers of ALL connected eNBs...add the eNB_index later
  // for more flexibility
256
  uint8_t i,j,k,s;
257
  PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
258

Bilel's avatar
Bilel committed
259
  //[NUMBER_OF_RX_THREAD=2][NUMBER_OF_CONNECTED_eNB_MAX][2];
260
  for(int l=0; l<RX_NB_TH; l++) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274
    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;
            }
Bilel's avatar
Bilel committed
275
          }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
276 277
        }
      }
278

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

      // flush Msg3 buffer
      ue->ulsch_Msg3_active[i] = 0;
    }
291 292 293
  }
}

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
294
void ra_failed(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) {
295
  // if contention resolution fails, go back to PRACH
knopp's avatar
knopp committed
296
  PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PRACH;
Bilel's avatar
Bilel committed
297 298 299 300
  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;
301
  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);
302 303
}

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
304
void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) {
305
  int i;
306
  LOG_I(PHY,"[UE %d][RAPROC] Random-access procedure succeeded. Set C-RNTI = Temporary C-RNTI\n",Mod_id);
Bilel's avatar
Bilel committed
307 308
  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;
309
  PHY_vars_UE_g[Mod_id][CC_id]->ulsch_Msg3_active[eNB_index] = 0;
knopp's avatar
knopp committed
310
  PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PUSCH;
311

312
  for (i=0; i<8; i++) {
313
    if (PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]) {
314
      PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->status=SCH_IDLE;
Bilel's avatar
Bilel committed
315 316
      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;
317
      PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->harq_processes[i]->subframe_scheduling_flag=0;
318
    }
319 320 321
  }
}

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
322
UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index) {
knopp's avatar
knopp committed
323
  return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index]);
324
}
325
void process_timing_advance_rar(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint16_t timing_advance) {
326
  ue->timing_advance = timing_advance*4;
327

328
  if (LOG_DEBUGFLAG(DEBUG_UE_PHYPROC)) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
329 330
    /* 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);*/
331 332
    LOG_UI(PHY,"[UE %d] AbsoluteSubFrame %d.%d, received (rar) timing_advance %d\n",ue->Mod_id,proc->frame_rx, proc->subframe_rx, ue->timing_advance);
  }
333 334
}

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
335
void process_timing_advance(module_id_t Mod_id,uint8_t CC_id,int16_t timing_advance) {
336
  //  uint32_t frame = PHY_vars_UE_g[Mod_id]->frame;
337
  // timing advance has Q1.5 format
338
  timing_advance = timing_advance - 31;
339
  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!!!
340
  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);
341 342
}

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
343
uint8_t is_SR_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id) {
344
  int subframe=proc->subframe_tx;
345
  LOG_D(PHY,"[UE %d][SR %x] Frame %d subframe %d Checking for SR TXOp (sr_ConfigIndex %d)\n",
346
        ue->Mod_id,ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->crnti,proc->frame_tx,subframe,
347
        ue->scheduling_request_config[eNB_id].sr_ConfigIndex);
348

349 350
  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)
351
      return(1);
352 353
  } 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))
354
      return(1);
355
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 34) { // 20 ms SR period
356
    if ((10*(proc->frame_tx&1)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-15))
357
      return(1);
358
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 74) { // 40 ms SR period
359
    if ((10*(proc->frame_tx&3)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-35))
360
      return(1);
361
  } else if (ue->scheduling_request_config[eNB_id].sr_ConfigIndex <= 154) { // 80 ms SR period
362
    if ((10*(proc->frame_tx&7)+subframe) == (ue->scheduling_request_config[eNB_id].sr_ConfigIndex-75))
363 364 365 366 367 368
      return(1);
  }

  return(0);
}

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
369
uint8_t is_cqi_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id) {
370 371 372 373 374 375 376 377 378
  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));

379 380 381
  if (cqirep->cqi_PMI_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe) % cqirep->Npd) == cqirep->N_OFFSET_CQI)
382 383 384 385
    return(1);
  else
    return(0);
}
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
386
uint8_t is_ri_TXOp(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id) {
387 388 389 390 391 392 393 394 395 396
  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));
397 398 399
  if (cqirep->ri_ConfigIndex==-1)
    return(0);
  else if (((10*frame + subframe + cqirep->N_OFFSET_CQI - N_OFFSET_RI) % (cqirep->Npd<<log2Mri)) == 0)
400 401 402 403 404
    return(1);
  else
    return(0);
}

Bilel's avatar
Bilel committed
405 406 407 408 409 410 411
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,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
412 413 414
                              uint8_t ri_status) {
  //PHY_MEASUREMENTS *meas = &ue->measurements;
  //uint8_t transmission_mode = ue->transmission_mode[eNB_id];
Bilel's avatar
Bilel committed
415

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
416 417 418 419
  //LOG_I(PHY,"compute_cqi_ri_resources O_RI %d O %d uci format %d \n",ulsch->O_RI,ulsch->O,ulsch->uci_format);
  if (cqi_status == 1 || ri_status == 1) {
    ulsch->O = 4;
  }
Bilel's avatar
Bilel committed
420 421
}

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
422
void ue_compute_srs_occasion(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t isSubframeSRS) {
423 424 425 426 427 428 429 430
  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
431 432
  // check for SRS opportunity
  pSoundingrs_ul_config_dedicated->srsUeSubframe   = 0;
433
  pSoundingrs_ul_config_dedicated->srsCellSubframe = isSubframeSRS;
Bilel's avatar
Bilel committed
434

435
  if (isSubframeSRS) {
436
    LOG_D(PHY," SrsDedicatedSetup: %d \n",pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup);
437

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
    if(pSoundingrs_ul_config_dedicated->srsConfigDedicatedSetup) {
      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 = ue_get_SR(Mod_id,
                                   CC_id,
                                   frame_tx,
                                   eNB_id,
                                   ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->crnti,
                                   subframe_tx); // subframe used for meas gap

            if (SR_payload > 0)
              is_sr_an_subframe = 1;
472
          }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
        }

        uint8_t pucch_ack_payload[2];

        if (get_ack(&ue->frame_parms,
                    ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack,
                    subframe_tx,proc->subframe_rx,pucch_ack_payload,0) > 0) {
          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
496
      }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
497 498 499 500
    }

    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
501 502 503
  }
}

504

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
505
void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id) {
knopp's avatar
knopp committed
506 507 508 509 510 511 512 513 514
  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;
515
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-2;
knopp's avatar
knopp committed
516 517
    } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
      cqirep->Npd = 10;
518
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-7;
knopp's avatar
knopp committed
519 520
    } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
      cqirep->Npd = 20;
521
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-17;
knopp's avatar
knopp committed
522 523
    } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
      cqirep->Npd = 40;
524
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-37;
knopp's avatar
knopp committed
525 526
    } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
      cqirep->Npd = 80;
527
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-77;
knopp's avatar
knopp committed
528 529
    } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
      cqirep->Npd = 160;
530
      cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-157;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
531
    } else if (cqi_PMI_ConfigIndex > 317) {
knopp's avatar
knopp committed
532
      if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
533 534 535 536 537 538 539 540
        cqirep->Npd = 32;
        cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-318;
      } else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period
        cqirep->Npd = 64;
        cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-350;
      } else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period
        cqirep->Npd = 128;
        cqirep->N_OFFSET_CQI = cqi_PMI_ConfigIndex-414;
541
      }
knopp's avatar
knopp committed
542
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
  } 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;
    }
knopp's avatar
knopp committed
566 567 568
  }
}

569 570 571 572 573
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
574
                             uint8_t ri_status,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
                             uint8_t bundling_flag) {
  if((cqi_status == 0) && (ri_status==0)) {
    // PUCCH Format 1 1a 1b
    // 1- SR only ==> PUCCH format 1
    // 2- 1bit Ack/Nack with/without SR  ==> PUCCH format 1a
    // 3- 2bits Ack/Nack with/without SR ==> PUCCH format 1b
    if((nb_cw == 1)&&(bundling_flag==bundling)) {
      return pucch_format1a;
    }

    if((nb_cw == 1)&&(bundling_flag==multiplexing)) {
      return pucch_format1b;
    }

    if(nb_cw == 2) {
      return pucch_format1b;
    }

    if(SR_payload == 1) {
      return pucch_format1;
      /*
      if (frame_type == FDD) {
Gabriel's avatar
Gabriel committed
597
          return pucch_format1;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
      } else if (frame_type == TDD) {
          return pucch_format1b;
      } else {
          AssertFatal(1==0,"Unknown frame_type");
      }*/
    }
  } 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;
617
      }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
618 619 620

      if(nb_cw == 2) {
        return pucch_format2b;
621
      }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
622 623 624
    } else {
      return pucch_format2;
    }
625
  }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
626

Bilel's avatar
Bilel committed
627
  return pucch_format1a;
628
}
629
uint16_t get_n1_pucch(PHY_VARS_UE *ue,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
630
                      UE_rxtx_proc_t *proc,
631
                      harq_status_t *harq_ack,
632 633
                      uint8_t eNB_id,
                      uint8_t *b,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
634
                      uint8_t SR) {
635
  LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
636
  uint8_t nCCE0,nCCE1,nCCE2,nCCE3,harq_ack1,harq_ack0,harq_ack3,harq_ack2;
637
  ANFBmode_t bundling_flag;
Gabriel's avatar
Gabriel committed
638
  uint16_t n1_pucch0=0,n1_pucch1=0,n1_pucch2=0,n1_pucch3=0,n1_pucch_inter;
639 640
  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
641 642
  int sf;
  int M;
643
  uint8_t ack_counter=0;
644
  // clear this, important for case where n1_pucch selection is not used
645
  int subframe=proc->subframe_tx;
646
  ue->pucch_sel[subframe] = 0;
647 648 649

  if (frame_parms->frame_type == FDD ) { // FDD
    sf = (subframe<4)? subframe+6 : subframe-4;
650
    LOG_D(PHY,"n1_pucch_UE: subframe %d, nCCE %d\n",sf,ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[sf]);
651 652

    if (SR == 0)
653
      return(frame_parms->pucch_config_common.n1PUCCH_AN + ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[sf]);
654
    else
655
      return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
656
  } else {
657
    bundling_flag = ue->pucch_config_dedicated[eNB_id].tdd_AckNackFeedbackMode;
658

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
659
    if (LOG_DEBUGFLAG(DEBUG_UE_PHYPROC)) {
660 661 662 663 664 665 666
      if (bundling_flag==bundling) {
        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,
              ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
      } else {
        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,
              ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
      }
667
    }
668

669
    switch (frame_parms->tdd_config) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
      case 1:  // DL:S:UL:UL:DL:DL:S:UL:UL:DL
        harq_ack0 = 2; // DTX
        M=1;

        // This is the offset for a particular subframe (2,3,4) => (0,2,4)
        if (subframe == 2) {  // ACK subframes 5,6
          candidate_dl[0] = 6;
          candidate_dl[1] = 5;
          M=2;
        } else if (subframe == 3) { // ACK subframe 9
          candidate_dl[0] = 9;
        } else if (subframe == 7) { // ACK subframes 0,1
          candidate_dl[0] = 1;
          candidate_dl[1] = 0;
          M=2;
        } else if (subframe == 8) { // ACK subframes 4
          candidate_dl[0] = 4;
        } else {
          LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal tx-subframe %d for tdd_config %d\n",
                ue->Mod_id,proc->frame_tx,subframe,frame_parms->tdd_config);
          return(0);
691 692
        }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
693 694
        // checking which downlink candidate is the last downlink with valid DL-DCI
        int k;
695

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
696 697 698 699 700 701
        for (k=0; k<M; k++) {
          if (harq_ack[candidate_dl[k]].send_harq_status>0) {
            last_dl = candidate_dl[k];
            break;
          }
        }
702

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
703 704 705 706 707
        if (last_dl >= 10) {
          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);
          return (0);
        }
708

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
        LOG_D(PHY,"SFN/SF %d/%d calculating n1_pucch0 from last_dl=%d\n",
              proc->frame_tx%1024,
              proc->subframe_tx,
              last_dl);
        // i=0
        nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[last_dl];
        n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
        harq_ack0 = b[0];

        if (harq_ack0!=2) {  // DTX
          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)
              ue->pucch_sel[subframe] = 0;
              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;
              return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
            }
729
          } else {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
730 731 732 733 734 735 736 737 738 739
            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);
            }
740
          }
741 742
        }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
        break;

      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)
        last_dl = (subframe-2)<<1;
        // i=0
        nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[5+last_dl];
        n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
        // i=1
        nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[(6+last_dl)%10];
        n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;

        // set ACK/NAK to values if not DTX
        if (ue->dlsch[ue->current_thread_id[proc->subframe_rx]][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[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[(6+last_dl)%10].ack;

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

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

        if (harq_ack1!=2) { // n-6 // subframe 6,8,0 and maybe 5,7,9 is to be ACK/NAKed
          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;
778

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
779 780
            if (harq_ack0!=2)
              b[0]=b[0]&harq_ack0;
781

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
782 783 784 785 786
            ue->pucch_sel[subframe] = 1;
            return(n1_pucch1);
          } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1
            if (harq_ack0 == 2)
              harq_ack0 = 0;
787

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
788 789 790 791 792 793 794 795 796 797 798 799 800 801
            b[1] = harq_ack0;
            b[0] = (harq_ack0!=harq_ack1)?0:1;

            if ((harq_ack0 == 1) && (harq_ack1 == 0)) {
              ue->pucch_sel[subframe] = 0;
              return(n1_pucch0);
            } else {
              ue->pucch_sel[subframe] = 1;
              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;
802

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
803 804 805 806 807 808 809
            b[0]= harq_ack1 | harq_ack0;
            b[1]= harq_ack1 ^ harq_ack0;
            return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
          }
        } 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;
810
            ue->pucch_sel[subframe] = 0;
811
            return(n1_pucch0);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
812 813 814 815 816 817 818 819 820
          } 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];
            ue->pucch_sel[subframe] = 0;
            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];
            return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
821 822 823
          }
        }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
824 825 826 827 828 829 830 831 832 833
        break;

      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
834

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
835 836 837
        // This is the offset for a particular subframe (2,3,4) => (0,2,4)
        //last_dl = (subframe-2)<<1;
        if (subframe == 2) {
838
          // i=0
839 840
          //nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[2+subframe];
          nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[(8+subframe)%10];
841 842
          n1_pucch0 = 2*get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
          // i=1
843
          nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[2+subframe];
844 845
          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
846
          nCCE2 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[(8+subframe)%10];
847
          n1_pucch2 = 2*get_Np(frame_parms->N_RB_DL,nCCE2,1) + nCCE2+ frame_parms->pucch_config_common.n1PUCCH_AN;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
848

849
          // i=3
850
          //nCCE3 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[(9+subframe)%10];
851 852 853
          //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
854 855
          if (ue->dlsch[ue->current_thread_id[proc->subframe_rx]][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[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[(8+subframe)%10].ack;
856

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

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

863
          //if (ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[(9+subframe)%10].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
864
          //harq_ack3 = ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[(9+subframe)%10].ack;
865 866 867 868 869
          //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);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
870
        } else if (subframe == 3) {
871
          // i=0
872
          nCCE0 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[4+subframe];
873 874
          n1_pucch0 = 3*get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
          // i=1
875
          nCCE1 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[5+subframe];
876 877
          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
878
          nCCE2 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[(6+subframe)];
879 880
          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
881
          nCCE3 = ue->pdcch_vars[ue->current_thread_id[proc->subframe_rx]][eNB_id]->nCCE[(3+subframe)];
882 883 884
          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
885
          if (ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[4+subframe].send_harq_status>0)  // n-6 // subframe 6 is to be ACK/NAKed
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
886
            harq_ack0 = ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[4+subframe].ack;
887

888
          if (ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[5+subframe].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
889
            harq_ack1 = ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[5+subframe].ack;
890

891
          if (ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[(6+subframe)].send_harq_status>0)  // n-6 // subframe 6 is to be ACK/NAKed
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
892
            harq_ack2 = ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[(6+subframe)].ack;
893

894
          if (ue->dlsch[ue->current_thread_id[proc->subframe_rx]][eNB_id][0]->harq_ack[(3+subframe)].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
            harq_ack3 = ue->dlsch[ue->current_thread_id[proc->subframe_rx]][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,
          b[0] = 1;
          ack_counter = 0;

          if ((harq_ack3!=2) ) {
            b[0] = b[0]&harq_ack3;
            n1_pucch_inter = n1_pucch3;
            ack_counter ++;
913 914
          }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
915 916 917 918 919
          if ((harq_ack0!=2) ) {
            b[0] = b[0]&harq_ack0;
            n1_pucch_inter = n1_pucch0;
            ack_counter ++;
          }
920

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
          if ((harq_ack1!=2) ) {
            b[0] = b[0]&harq_ack1;
            n1_pucch_inter = n1_pucch1;
            ack_counter ++;
          }

          if ((harq_ack2!=2) ) {
            b[0] = b[0]&harq_ack2;
            n1_pucch_inter = n1_pucch2;
            ack_counter ++;
          }

          if (ack_counter == 0)
            b[0] = 0;

          /*if (subframe == 3) {
             n1_pucch_inter = n1_pucch2;
          } else if (subframe == 2) {
             n1_pucch_inter = n1_pucch1;
          }*/
          //LOG_I(PHY,"SFN/SF %d/%d calculating n1_pucch n1_pucch_inter=%d  b[0]=%d b[1]=%d \n",
          //                                           proc->frame_tx%1024,
          //                                           proc->subframe_tx,n1_pucch_inter,
          //                                           b[0],b[1]);
          return(n1_pucch_inter);
        } else if ((bundling_flag==multiplexing)&&(SR==0)) { // Table 10.1
          if (subframe == 3) {
            LOG_I(PHY, "sbuframe=%d \n",subframe);

            if ((harq_ack0 == 1) && (harq_ack1 == 1) && (harq_ack2 == 1) && (harq_ack3 == 1)) {
              b[0] = 1;
              b[1] = 1;
              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;
              b[1] = 1;
              return(n1_pucch2);
            } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && (harq_ack3 == 1)) {
              b[0] = 1;
              b[1] = 0;
              return(n1_pucch1);
            } else if ((harq_ack0 == 0) && (harq_ack1 == 2) && (harq_ack2 == 2) && (harq_ack3 == 2)) {
              b[0] = 1;
              b[1] = 0;
              return(n1_pucch0);
            } else if ((harq_ack0 == 1) && (harq_ack1 == 1) && ((harq_ack2 == 2) || (harq_ack2 == 0)) && ((harq_ack3 == 2) || (harq_ack3 == 0))) {
              b[0] = 1;
              b[1] = 0;
              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;
              b[1] = 1;
              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);
            }
          } 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);
1068
            }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1069 1070 1071 1072
          }
        } 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
          ack_counter = 0;
1073

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
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 1105 1106 1107 1108 1109 1110
          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;
1111 1112
          }

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1113 1114 1115
          ack_counter = 0;
          return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
        }
1116

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1117
        break;
1118
    }  // switch tdd_config
1119
  }
1120

Cedric Roux's avatar
Cedric Roux committed
1121
  LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, exit without proper return\n", ue->Mod_id, proc->frame_tx);
1122 1123 1124 1125
  return(-1);
}


Bilel's avatar
Bilel committed
1126
void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empty_subframe) {
1127
  int aa;
1128
  LTE_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
1129 1130 1131
  int nsymb;
  int subframe_tx = proc->subframe_tx;
  int ulsch_start;
1132
  int overflow=0;
1133
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
1134
  int k,l;
1135
  int dummy_tx_buffer[frame_parms->samples_per_tti] __attribute__((aligned(16)));
1136
#endif
1137
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1138

1139 1140 1141
  if ( LOG_DEBUGFLAG(UE_TIMING)) {
    start_meas(&ue->ofdm_mod_stats);
  }
1142

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1143
  nsymb = (frame_parms->Ncp == 0) ? 14 : 12;
1144 1145
#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-
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1146 1147 1148
                 ue->hw_timing_advance-
                 ue->timing_advance-
                 ue->N_TA_offset+5);
Gabriel's avatar
Gabriel committed
1149 1150 1151
  //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);

  if(ulsch_start < 0)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1152
    ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
Gabriel's avatar
Gabriel committed
1153 1154

  if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti))
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1155
    ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
Gabriel's avatar
Gabriel committed
1156 1157

  //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);
1158 1159 1160
#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
1161

Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1162
  if (empty_subframe) {
1163
    overflow = ulsch_start - 9*frame_parms->samples_per_tti;
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1164

1165
    for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1166 1167 1168 1169 1170 1171
      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],0,4*overflow);
      } else {
        memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*frame_parms->samples_per_tti);
      }
1172
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1173

1174
    return;
Bilel's avatar
Bilel committed
1175
  }
1176

1177 1178 1179 1180
  for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
    if (frame_parms->Ncp == 1)
      PHY_ofdm_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size],
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1181
                   dummy_tx_buffer,
1182
#else
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1183
                   &ue->common_vars.txdata[aa][ulsch_start],
1184
#endif
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1185 1186 1187 1188
                   frame_parms->ofdm_symbol_size,
                   nsymb,
                   frame_parms->nb_prefix_samples,
                   CYCLIC_PREFIX);
1189
    else {
1190 1191
      normal_prefix_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size],
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1192
                        dummy_tx_buffer,
1193
#else
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1194
                        &ue->common_vars.txdata[aa][ulsch_start],
1195
#endif
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1196 1197
                        nsymb>>1,
                        &ue->frame_parms);
1198 1199
      normal_prefix_mod(&ue->common_vars.txdataF[aa][((subframe_tx*nsymb)+(nsymb>>1))*frame_parms->ofdm_symbol_size],
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1200
                        dummy_tx_buffer+(frame_parms->samples_per_tti>>1),
1201
#else
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1202
                        &ue->common_vars.txdata[aa][ulsch_start+(frame_parms->samples_per_tti>>1)],
1203
#endif
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1204 1205
                        nsymb>>1,
                        &ue->frame_parms);
1206
    }
1207

1208 1209 1210 1211 1212 1213 1214 1215 1216
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
    apply_7_5_kHz(ue,dummy_tx_buffer,0);
    apply_7_5_kHz(ue,dummy_tx_buffer,1);
#else
    apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],0);
    apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],1);
#endif
#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
    overflow = ulsch_start - 9*frame_parms->samples_per_tti;
1217

1218
    for (k=ulsch_start,l=0; k<cmin(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_tti); k++,l++) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1219 1220
      ((short *)ue->common_vars.txdata[aa])[2*k] = ((short *)dummy_tx_buffer)[2*l];
      ((short *)ue->common_vars.txdata[aa])[2*k+1] = ((short *)dummy_tx_buffer)[2*l+1];
1221
    }
1222

1223
    for (k=0; k<overflow; k++,l++) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1224 1225
      ((short *)ue->common_vars.txdata[aa])[2*k] = ((short *)dummy_tx_buffer)[2*l];
      ((short *)ue->common_vars.txdata[aa])[2*k+1] = ((short *)dummy_tx_buffer)[2*l+1];
1226
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1227

1228
#if defined(EXMIMO)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1229

1230 1231 1232
    // handle switch before 1st TX subframe, guarantee that the slot prior to transmission is switch on
    for (k=ulsch_start - (frame_parms->samples_per_tti>>1) ; k<ulsch_start ; k++) {
      if (k<0)
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1233
        ue->common_vars.txdata[aa][k+frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
1234
      else if (k>(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME))
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1235
        ue->common_vars.txdata[aa][k-frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
1236
      else
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1237
        ue->common_vars.txdata[aa][k] &= 0xFFFEFFFE;
1238
    }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
1239

1240
#endif
1241
#endif
1242 1243 1244 1245 1246 1247
    /*
    only for debug
    LOG_I(PHY,"ul-signal [subframe: %d, ulsch_start %d, TA: %d, rxOffset: %d, timing_advance: %d, hw_timing_advance: %d]\n",subframe_tx, ulsch_start, ue->N_TA_offset, ue->rx_offset, ue->timing_advance, ue->hw_timing_advance);
    if( (crash == 1) && (subframe_tx == 0) )
    {
      LOG_E(PHY,"***** DUMP TX Signal [ulsch_start %d] *****\n",ulsch_start);
Mongazon's avatar
Mongazon committed
1248
      LOG_M("txBuff.m","txSignal",&ue->common_vars.txdata[aa][ulsch_start],frame_parms->samples_per_tti,1,1);
1249 1250
    }
    */
1251
  } //nb_antennas_tx
1252

1253 1254 1255
  if ( LOG_DEBUGFLAG(UE_TIMING)) {
    stop_meas(&ue->ofdm_mod_stats);
  }
1256

1257
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_OUT);
1258
}
1259

1260 1261 1262
void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mode) {
  int frame_tx = proc->frame_tx;
  int subframe_tx = proc->subframe_tx;
1263
  LOG_USEDINLOG_VAR(int, prach_power);
1264
  PRACH_RESOURCES_t prach_resources_local;