pucch_nr.c 67.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * 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.1  (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
 */

/*! \file PHY/NR_UE_TRANSPORT/pucch_nr.c
* \brief Top-level routines for generating and decoding the PUCCH physical channel
* \author A. Mico Pereperez
* \date 2018
* \version 0.1
* \company Eurecom
28
* \email:
29 30 31 32 33 34
* \note
* \warning
*/
//#include "PHY/defs.h"
#include "PHY/impl_defs_nr.h"
#include "PHY/defs_nr_common.h"
35
#include "PHY/defs_nr_UE.h"
36
//#include "PHY/extern.h"
37
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
38
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
Francesco Mani's avatar
Francesco Mani committed
39
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
laurent's avatar
laurent committed
40
#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
41 42
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
43 44

#include "T.h"
45
//#define NR_UNIT_TEST 1
Agustin's avatar
Agustin committed
46
#ifdef NR_UNIT_TEST
47 48 49
  #define DEBUG_PUCCH_TX
  #define DEBUG_NR_PUCCH_TX
#endif
Francesco Mani's avatar
Francesco Mani committed
50

51
//#define ONE_OVER_SQRT2 23170 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
52
//#define POLAR_CODING_DEBUG
53

laurent's avatar
laurent committed
54
void nr_generate_pucch0(const PHY_VARS_NR_UE *ue,
55
                        c16_t **txdataF,
laurent's avatar
laurent committed
56 57 58 59
                        const NR_DL_FRAME_PARMS *frame_parms,
                        const int16_t amp,
                        const int nr_slot_tx,
                        const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
60
{
61
#ifdef DEBUG_NR_PUCCH_TX
62
  printf("\t [nr_generate_pucch0] start function at slot(nr_slot_tx)=%d\n",nr_slot_tx);
63
#endif
64 65 66 67
  /*
   * Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
   *
   */
68 69 70
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch0] sequence generation\n");
#endif
71 72 73 74 75 76
  /*
   * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
   */
  // alpha is cyclic shift
  double alpha;
  // lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
yilmazt's avatar
yilmazt committed
77
  //uint8_t lnormal;
78
  // lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
yilmazt's avatar
yilmazt committed
79
  //uint8_t lprime;
80 81 82 83 84 85 86 87 88 89 90 91
  // mcs is provided by TC 38.213 subclauses 9.2.3, 9.2.4, 9.2.5 FIXME!
  //uint8_t mcs;
  /*
   * in TS 38.213 Subclause 9.2.1 it is said that:
   * for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift
   * is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift
   */
  /*
   * Implementing TS 38.211 Subclause 6.3.2.3.1, the sequence x(n) shall be generated according to:
   * x(l*12+n) = r_u_v_alpha_delta(n)
   */
  // the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
92 93
  uint8_t u[2]={0,0},v[2]={0,0};

94 95
  LOG_D(PHY,"pucch0: slot %d nr_symbols %d, start_symbol %d, prb_start %d, second_hop_prb %d,  group_hop_flag %d, sequence_hop_flag %d, mcs %d\n",
        nr_slot_tx,pucch_pdu->nr_of_symbols,pucch_pdu->start_symbol_index,pucch_pdu->prb_start,pucch_pdu->second_hop_prb,pucch_pdu->group_hop_flag,pucch_pdu->sequence_hop_flag,pucch_pdu->mcs);
96

Jacques's avatar
Jacques committed
97
#ifdef DEBUG_NR_PUCCH_TX
98
  printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n");
Jacques's avatar
Jacques committed
99
#endif
100
  // x_n contains the sequence r_u_v_alpha_delta(n)
101
  int16_t x_n_re[2][24],x_n_im[2][24];
102

103 104 105
  uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
  pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);

106
  // we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2
107
  int prb_offset[2]={startingPRB,startingPRB};
108 109 110
  nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,0,nr_slot_tx,&u[0],&v[0]); // calculating u and v value
  if (pucch_pdu->freq_hop_flag == 1) {
    nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,1,nr_slot_tx,&u[1],&v[1]); // calculating u and v value
111
    prb_offset[1] = pucch_pdu->second_hop_prb + pucch_pdu->bwp_start;
112
  }
113 114 115 116 117 118
  for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
    alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,
                                    pucch_pdu->initial_cyclic_shift,
                                    pucch_pdu->mcs,l,
                                    pucch_pdu->start_symbol_index,
                                    nr_slot_tx);
luis_pereira87's avatar
luis_pereira87 committed
119
#ifdef DEBUG_NR_PUCCH_TX
120
    printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u[l],v[l],alpha,l);
luis_pereira87's avatar
luis_pereira87 committed
121
#endif
122 123

    for (int n=0; n<12; n++) {
124 125 126 127
      x_n_re[l][n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u[l]][n])>>15)
                                    - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u[l]][n])>>15))); // Re part of base sequence shifted by alpha
      x_n_im[l][n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u[l]][n])>>15)
                                    + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u[l]][n])>>15))); // Im part of base sequence shifted by alpha
128 129
#ifdef DEBUG_NR_PUCCH_TX
      printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \tx_n(l=%d,n=%d)=(%d,%d)\n",
130
             u[l],v[l],alpha,l,n,x_n_re[l][n],x_n_im[l][n]);
131
#endif
132 133
    }
  }
134

135 136 137
  /*
   * Implementing TS 38.211 Subclause 6.3.2.3.2 Mapping to physical resources FIXME!
   */
138 139
  //int32_t *txptr;
  uint32_t re_offset=0;
Francesco Mani's avatar
Francesco Mani committed
140
  uint8_t l2;
141

142 143
  for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
    l2=l+pucch_pdu->start_symbol_index;
144
    re_offset = (12*prb_offset[l]) + frame_parms->first_carrier_offset;
145 146
    if (re_offset>= frame_parms->ofdm_symbol_size) 
      re_offset-=frame_parms->ofdm_symbol_size;
147

148
    //txptr = &txdataF[0][re_offset];
149
#ifdef DEBUG_NR_PUCCH_TX
150
    printf("\t [nr_generate_pucch0] symbol %d PRB %d (%u)\n",l,prb_offset[l],re_offset);
151
#endif    
152 153
    for (int n=0; n<12; n++) {

154 155
      txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r = (int16_t)(((int32_t)(amp) * x_n_re[l][n])>>15);
      txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].i = (int16_t)(((int32_t)(amp) * x_n_im[l][n])>>15);
156 157 158
      //((int16_t *)txptr[0][re_offset])[0] = (int16_t)((int32_t)amp * x_n_re[(12*l)+n])>>15;
      //((int16_t *)txptr[0][re_offset])[1] = (int16_t)((int32_t)amp * x_n_im[(12*l)+n])>>15;
      //txptr[re_offset] = (x_n_re[(12*l)+n]<<16) + x_n_im[(12*l)+n];
159
#ifdef DEBUG_NR_PUCCH_TX
160
      printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
161 162 163
             amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, (l2 * frame_parms->ofdm_symbol_size) + re_offset,
             l2, n, txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].r,
             txdataF[0][(l2*frame_parms->ofdm_symbol_size) + re_offset].i);
164
#endif
165
      re_offset++;
166 167
      if (re_offset>= frame_parms->ofdm_symbol_size) 
        re_offset-=frame_parms->ofdm_symbol_size;
168 169 170
    }
  }
}
171

laurent's avatar
laurent committed
172
void nr_generate_pucch1(const PHY_VARS_NR_UE *ue,
173
                        c16_t **txdataF,
laurent's avatar
laurent committed
174 175 176 177
                        const NR_DL_FRAME_PARMS *frame_parms,
                        const int16_t amp,
                        const int nr_slot_tx,
                        const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
178
{
179 180 181 182 183 184 185
  uint16_t m0 = pucch_pdu->initial_cyclic_shift;
  uint64_t payload = pucch_pdu->payload;
  uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index;
  uint8_t nrofSymbols = pucch_pdu->nr_of_symbols;
  uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
  uint8_t timeDomainOCC = pucch_pdu->time_domain_occ_idx;

186
#ifdef DEBUG_NR_PUCCH_TX
187 188
  printf("\t [nr_generate_pucch1] start function at slot(nr_slot_tx)=%d payload=%lu m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d second_hop_prb=%d timeDomainOCC=%d nr_bit=%d\n",
         nr_slot_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,pucch_pdu->second_hop_prb,timeDomainOCC,pucch_pdu->n_bit);
189 190
#endif
  /*
191 192 193 194
   * Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation
   *
   */
  // complex-valued symbol d_re, d_im containing complex-valued symbol d(0):
195
  int16_t d_re = 0, d_im = 0;
196

197
  if (pucch_pdu->n_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2
198 199 200
    d_re = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    d_im = (payload&1)==0 ? (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15) : -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
  }
201

202
  if (pucch_pdu->n_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2
203
    if (((payload&1)==0) && (((payload>>1)&1)==0)) {
204 205
      d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15); // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
      d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
206
    }
207

208
    if (((payload&1)==0) && (((payload>>1)&1)==1)) {
209
      d_re = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
210 211
      d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    }
212

213 214
    if (((payload&1)==1) && (((payload>>1)&1)==0)) {
      d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
215
      d_im = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
216
    }
217

218 219 220 221 222
    if (((payload&1)==1) && (((payload>>1)&1)==1)) {
      d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      d_im = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    }
  }
223
//  printf("d_re=%d\td_im=%d\n",(int)d_re,(int)d_im);
224
#ifdef DEBUG_NR_PUCCH_TX
225
  printf("\t [nr_generate_pucch1] sequence modulation: payload=%lx \tde_re=%d \tde_im=%d\n",payload,d_re,d_im);
226
#endif
227 228 229 230
  /*
   * Defining cyclic shift hopping TS 38.211 Subclause 6.3.2.2.2
   */
  // lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
yilmazt's avatar
yilmazt committed
231
  //uint8_t lnormal = 0 ;
232
  /*
233 234 235 236 237 238 239 240
   * in TS 38.213 Subclause 9.2.1 it is said that:
   * for PUCCH format 0 or PUCCH format 1, the index of the cyclic shift
   * is indicated by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift
   */
  /*
   * the complex-valued symbol d_0 shall be multiplied with a sequence r_u_v_alpha_delta(n): y(n) = d_0 * r_u_v_alpha_delta(n)
   */
  // the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
yilmazt's avatar
yilmazt committed
241
  uint8_t u=0,v=0;//,delta=0;
242 243 244 245 246 247 248 249 250 251 252
  // if frequency hopping is disabled, intraSlotFrequencyHopping is not provided
  //              n_hop = 0
  // if frequency hopping is enabled,  intraSlotFrequencyHopping is     provided
  //              n_hop = 0 for first hop
  //              n_hop = 1 for second hop
  uint8_t n_hop = 0;
  // Intra-slot frequency hopping shall be assumed when the higher-layer parameter intraSlotFrequencyHopping is provided,
  // regardless of whether the frequency-hop distance is zero or not,
  // otherwise no intra-slot frequency hopping shall be assumed
  //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers
  uint8_t intraSlotFrequencyHopping = 0;
253

254
  if (pucch_pdu->freq_hop_flag) {
255
    intraSlotFrequencyHopping = 1;
256
  }
257

Agustin's avatar
Agustin committed
258
#ifdef DEBUG_NR_PUCCH_TX
259
  printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n", intraSlotFrequencyHopping);
Agustin's avatar
Agustin committed
260
#endif
261 262 263
  /*
   * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources
   */
264 265
  //int32_t *txptr;
  uint32_t re_offset=0;
266
  int i=0;
267
#define MAX_SIZE_Z 168 // this value has to be calculated from mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n
268 269 270
  int16_t z_re[MAX_SIZE_Z],z_im[MAX_SIZE_Z];
  int16_t z_dmrs_re[MAX_SIZE_Z],z_dmrs_im[MAX_SIZE_Z];

271 272 273 274
  // lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
  uint8_t lprime = startingSymbolIndex;

  for (int l = 0; l < nrofSymbols; l++) {
275 276 277 278
#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n",
           l,lprime);
#endif
279 280
    // y_n contains the complex value d multiplied by the sequence r_u_v
    int16_t y_n_re[12],y_n_im[12];
281

282 283
    if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols / 2)))
      n_hop = 1; // n_hop = 1 for second hop
284 285

#ifdef DEBUG_NR_PUCCH_TX
286 287
    printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_slot_tx=%d\n",
           n_hop,nr_slot_tx);
288
#endif
289 290
    pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
    nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,nr_slot_tx,&u,&v); // calculating u and v value
291 292 293 294 295 296 297 298
    // mcs = 0 except for PUCCH format 0
    int mcs = 0;
    double alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id, m0, mcs, l, lprime, nr_slot_tx);

    // r_u_v_alpha_delta_re and r_u_v_alpha_delta_im tables containing the sequence y(n) for the PUCCH, when they are multiplied by d(0)
    // r_u_v_alpha_delta_dmrs_re and r_u_v_alpha_delta_dmrs_im tables containing the sequence for the DM-RS.
    int16_t r_u_v_alpha_delta_re[12], r_u_v_alpha_delta_im[12], r_u_v_alpha_delta_dmrs_re[12], r_u_v_alpha_delta_dmrs_im[12];
    for (int n = 0; n < 12; n++) {
299
      r_u_v_alpha_delta_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
300
                                           - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of base sequence shifted by alpha
301
      r_u_v_alpha_delta_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
302
                                           + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of base sequence shifted by alpha
303
      r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
304
                                     - (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15))); // Re part of DMRS base sequence shifted by alpha
305
      r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
306
                                     + (((int32_t)(round(32767*sin(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15))); // Im part of DMRS base sequence shifted by alpha
Agustin's avatar
Agustin committed
307 308
      r_u_v_alpha_delta_dmrs_re[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_re[n]))>>15);
      r_u_v_alpha_delta_dmrs_im[n] = (int16_t)(((int32_t)(amp*r_u_v_alpha_delta_dmrs_im[n]))>>15);
309
//      printf("symbol=%d\tr_u_v_re=%d\tr_u_v_im=%d\n",l,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n]);
310 311
      // PUCCH sequence = DM-RS sequence multiplied by d(0)
      y_n_re[n]               = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_re)>>15)
312
                                           - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n)
313
      y_n_im[n]               = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15)
314
                                           + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n)
315
//       printf("symbol=%d\tr_u_v_dmrs_re=%d\tr_u_v_dmrs_im=%d\n",l,r_u_v_alpha_delta_dmrs_re[n],r_u_v_alpha_delta_dmrs_im[n]);
316 317 318 319
#ifdef DEBUG_NR_PUCCH_TX
      printf("\t [nr_generate_pucch1] sequence generation \tu=%d \tv=%d \talpha=%lf \tr_u_v_alpha_delta[n=%d]=(%d,%d) \ty_n[n=%d]=(%d,%d)\n",
             u,v,alpha,n,r_u_v_alpha_delta_re[n],r_u_v_alpha_delta_im[n],n,y_n_re[n],y_n_im[n]);
#endif
320
    }
321

322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
    /*
     * The block of complex-valued symbols y(n) shall be block-wise spread with the orthogonal sequence wi(m)
     * (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im)
     * z(mprime*12*table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n)=wi(m)*y(n)
     *
     * The block of complex-valued symbols r_u_v_alpha_dmrs_delta(n) for DM-RS shall be block-wise spread with the orthogonal sequence wi(m)
     * (defined in table_6_3_2_4_1_2_Wi_Re and table_6_3_2_4_1_2_Wi_Im)
     * z(mprime*12*table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[pucch_symbol_length]+m*12+n)=wi(m)*y(n)
     *
     */
    // the orthogonal sequence index for wi(m) defined in TS 38.213 Subclause 9.2.1
    // the index of the orthogonal cover code is from a set determined as described in [4, TS 38.211]
    // and is indicated by higher layer parameter PUCCH-F1-time-domain-OCC
    // In the PUCCH_Config IE, the PUCCH-format1, timeDomainOCC field
    uint8_t w_index = timeDomainOCC;
    // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1   (depending on number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled)
    uint8_t N_SF_mprime_PUCCH_1;
    // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime and intra-slot hopping enabled/disabled)
    uint8_t N_SF_mprime_PUCCH_DMRS_1;
    // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.3.2.4.1-1   (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
    uint8_t N_SF_mprime0_PUCCH_1;
    // N_SF_mprime_PUCCH_1 contains N_SF_mprime from table 6.4.1.3.1.1-1 (depending on number of PUCCH symbols nrofSymbols, mprime=0 and intra-slot hopping enabled/disabled)
    uint8_t N_SF_mprime0_PUCCH_DMRS_1;
    // mprime is 0 if no intra-slot hopping / mprime is {0,1} if intra-slot hopping
    uint8_t mprime = 0;
347

348
    if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled
349 350 351 352
#ifdef DEBUG_NR_PUCCH_TX
      printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping disabled\n",
             intraSlotFrequencyHopping);
#endif
353 354 355 356
      N_SF_mprime_PUCCH_1       =   table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (PUCCH)
      N_SF_mprime_PUCCH_DMRS_1  = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled (DM-RS)
      N_SF_mprime0_PUCCH_1      =   table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (PUCCH)
      N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_noHop[nrofSymbols-1]; // only if intra-slot hopping not enabled mprime = 0 (DM-RS)
357 358 359 360 361 362 363
#ifdef DEBUG_NR_PUCCH_TX
      printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n",
             w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1);
#endif

      for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
        for (int n=0; n<12 ; n++) {
364
          z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)
365
              - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15));
366
          z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)
367 368 369 370 371 372 373 374
              + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15));
#ifdef DEBUG_NR_PUCCH_TX
          printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
                 mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
                 table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],
                 table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],
                 z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#endif
375 376
        }
      }
377 378 379

      for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
        for (int n=0; n<12 ; n++) {
380 381 382 383
          z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)
              - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15));
          z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)
              + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15));
384 385 386 387 388 389 390
#ifdef DEBUG_NR_PUCCH_TX
          printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
                 mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
                 table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],
                 table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],
                 z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
#endif
391 392
//          printf("gNB entering l=%d\tdmrs_re=%d\tdmrs_im=%d\n",l,z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n],z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n]);
	}
393 394
      }
    }
395

396
    if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled
397 398 399 400
#ifdef DEBUG_NR_PUCCH_TX
      printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d, intra-slot hopping enabled\n",
             intraSlotFrequencyHopping);
#endif
401 402 403 404
      N_SF_mprime_PUCCH_1       =   table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
      N_SF_mprime_PUCCH_DMRS_1  = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
      N_SF_mprime0_PUCCH_1      =   table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (PUCCH)
      N_SF_mprime0_PUCCH_DMRS_1 = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m0Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 0 (DM-RS)
405 406 407 408 409
#ifdef DEBUG_NR_PUCCH_TX
      printf("\t [nr_generate_pucch1] w_index = %d, N_SF_mprime_PUCCH_1 = %d, N_SF_mprime_PUCCH_DMRS_1 = %d, N_SF_mprime0_PUCCH_1 = %d, N_SF_mprime0_PUCCH_DMRS_1 = %d\n",
             w_index, N_SF_mprime_PUCCH_1,N_SF_mprime_PUCCH_DMRS_1,N_SF_mprime0_PUCCH_1,N_SF_mprime0_PUCCH_DMRS_1);
#endif

410 411 412 413 414 415 416
      for (mprime = 0; mprime<2; mprime++) { // mprime can get values {0,1}
        for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
          for (int n=0; n<12 ; n++) {
            z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]           = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15)
                - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15));
            z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]           = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15)
                + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15));
417
#ifdef DEBUG_NR_PUCCH_TX
418 419 420 421 422
            printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
                   mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
                   table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],
                   table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],y_n_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],y_n_re[n],
                   z_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
Agustin's avatar
Agustin committed
423
#endif
424
          }
425
        }
426

427 428 429 430 431 432
        for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
          for (int n=0; n<12 ; n++) {
            z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)
                - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15));
            z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+n] = (int16_t)((((int32_t)(table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)
                + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_DMRS_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15));
433
#ifdef DEBUG_NR_PUCCH_TX
434 435 436 437 438
            printf("\t [nr_generate_pucch1] block-wise spread with wi(m) (mprime=%d, m=%d, n=%d) z[%d] = ((%d * %d - %d * %d), (%d * %d + %d * %d)) = (%d,%d)\n",
                   mprime, m, n, (mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n,
                   table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],
                   table_6_3_2_4_1_2_Wi_Re[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_im[n],table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m],r_u_v_alpha_delta_dmrs_re[n],
                   z_dmrs_re[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n],z_dmrs_im[(mprime*12*N_SF_mprime0_PUCCH_1)+(m*12)+n]);
Agustin's avatar
Agustin committed
439
#endif
440 441
          }
        }
442 443 444

        N_SF_mprime_PUCCH_1       =   table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (PUCCH)
        N_SF_mprime_PUCCH_DMRS_1  = table_6_4_1_3_1_1_1_N_SF_mprime_PUCCH_1_m1Hop[nrofSymbols-1]; // only if intra-slot hopping enabled mprime = 1 (DM-RS)
Agustin's avatar
Agustin committed
445
      }
446
    }
447

448 449
    if (n_hop) { // intra-slot hopping enabled, we need to calculate new offset PRB
      startingPRB = pucch_pdu->second_hop_prb + pucch_pdu->bwp_start;
450
    }
451

452
    if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band
453 454
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }
455

456 457 458
    if ((startingPRB >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1)));
    }
459

460
    if ((startingPRB < (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB is lower band
461 462
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }
463

464
    if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB is upper band
465 466
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6;
    }
467

468 469 470 471
    if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB contains DC
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }

472 473
    for (int n = 0; n < 12; n++) {
      if ((n == 6) && (startingPRB == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 1)) {
474 475 476
        // if number RBs in bandwidth is odd  and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
      }
477

478
      if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1
479 480
        txdataF[0][re_offset].r = z_re[i+n];
        txdataF[0][re_offset].i = z_im[i+n];
481
#ifdef DEBUG_NR_PUCCH_TX
482
        printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
483 484
               amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, i + n, re_offset,
               l, n, txdataF[0][re_offset].r, txdataF[0][re_offset].i);
485
#endif
486
      }
487

488 489 490
      if (l % 2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1
        txdataF[0][re_offset].r = z_dmrs_re[i+n];
        txdataF[0][re_offset].i = z_dmrs_im[i+n];
491
#ifdef DEBUG_NR_PUCCH_TX
492
        printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
493 494
               amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, i+n, re_offset,
               l, n, txdataF[0][re_offset].r, txdataF[0][re_offset].i);
495
#endif
496
//      printf("gNb l=%d\ti=%d\treoffset=%d\tre=%d\tim=%d\n",l,i,re_offset,z_dmrs_re[i+n],z_dmrs_im[i+n]);
497
      }
498
      
499 500
      re_offset++;
    }
501

502 503
    if (l % 2 == 1)
      i += 12;
504 505 506
  }
}

507 508
static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint64_t *B64,uint8_t *btilde) __attribute__((always_inline));
static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint64_t *B64,uint8_t *btilde) {
509
  uint32_t x1 = 0, x2 = 0, s = 0;
510 511 512
  int i;
  uint8_t c;
  // c_init=nRNTI*2^15+n_id according to TS 38.211 Subclause 6.3.2.6.1
513
  //x2 = (rnti) + ((uint32_t)(1+nr_slot_tx)<<16)*(1+(fp->Nid_cell<<1));
514
  x2 = ((rnti)<<15)+n_id;
515
#ifdef DEBUG_NR_PUCCH_TX
516
  printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%x, M_bit %d\n",s,M_bit);
517
#endif
518

Raymond Knopp's avatar
Raymond Knopp committed
519 520
  uint8_t *btildep=btilde;
  int M_bit2=M_bit > 31 ? 32 : (M_bit&31), M_bit3=M_bit;
521
  uint32_t B;
Raymond Knopp's avatar
Raymond Knopp committed
522 523
  for (int iprime=0;iprime<=(M_bit>>5);iprime++,btildep+=32) {
    s = lte_gold_generic(&x1, &x2, (iprime==0) ? 1 : 0);
524 525 526 527 528 529 530 531 532 533 534 535
    B=((uint32_t*)B64)[iprime];
    for (int n=0;n<M_bit2;n+=8)
      LOG_D(PHY,"PUCCH2 encoded %d : %d,%d,%d,%d,%d,%d,%d,%d\n",n,
	    (B>>n)&1,
	    (B>>(n+1))&1,
	    (B>>(n+2))&1,
	    (B>>(n+3))&1,
	    (B>>(n+4))&1,
	    (B>>(n+5))&1,
	    (B>>(n+6))&1,
	    (B>>(n+7))&1
	    );
Raymond Knopp's avatar
Raymond Knopp committed
536 537 538
    for (i=0; i<M_bit2; i++) {
      c = (uint8_t)((s>>i)&1);
      btildep[i] = (((B>>i)&1) ^ c);
539
#ifdef DEBUG_NR_PUCCH_TX
540
      printf("\t\t\t btilde[%d]=%x from unscrambled bit %d and scrambling %d (%x)\n",i+(iprime<<5),btilde[i],((B>>i)&1),c,s>>i);
541
#endif
Raymond Knopp's avatar
Raymond Knopp committed
542 543 544
    }
    M_bit3-=32;
    M_bit2=M_bit3 > 31 ? 32 : (M_bit3&31);
545 546
  }

Raymond Knopp's avatar
Raymond Knopp committed
547

548
#ifdef DEBUG_NR_PUCCH_TX
549
  printf("\t\t [nr_pucch2_3_4_scrambling] scrambling M_bit=%d bits\n", M_bit);
550
#endif
551
}
552
static void nr_uci_encoding(uint64_t payload,
553
                     uint8_t nr_bit,
554
                     int fmt,
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
                     uint8_t is_pi_over_2_bpsk_enabled,
                     uint8_t nrofSymbols,
                     uint8_t nrofPRB,
                     uint8_t n_SF_PUCCH_s,
                     uint8_t intraSlotFrequencyHopping,
                     uint8_t add_dmrs,
                     uint64_t *b,
                     uint16_t *M_bit) {
  /*
   * Implementing TS 38.212 Subclause 6.3.1.2
   *
   */
  // A is the payload size, to be provided in function call
  uint8_t A = nr_bit;
  // L is the CRC size
570
  //uint8_t L;
571
  // E is the rate matching output sequence length as given in TS 38.212 subclause 6.3.1.4.1
572
  uint16_t E=0,E_init;
573

574
  if (fmt == 2) E = 16*nrofSymbols*nrofPRB;
575

576
  if (fmt == 3) {
577
    E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12;
578

579 580
    if (nrofSymbols == 4) {
      E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)*nrofPRB):((E_init*(nrofSymbols-1)*nrofPRB));
581 582 583
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 3 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E);
#endif
584
    }
585

586 587
    if (nrofSymbols > 4)  {
      E = E_init*(nrofSymbols-2)*nrofPRB;
588 589 590
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 3 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E);
#endif
591
    }
592

593 594
    if (nrofSymbols > 9)  {
      E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)*nrofPRB):((E_init*(nrofSymbols-4)*nrofPRB));
595 596 597
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 3 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E);
#endif
598 599
    }
  }
600

601
  if (fmt == 4) {
602
    E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12;
603

604 605
    if (nrofSymbols == 4) {
      E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)/n_SF_PUCCH_s):((E_init*(nrofSymbols-1)/n_SF_PUCCH_s));
606 607 608
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 4 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E);
#endif
609
    }
610

611 612
    if (nrofSymbols > 4)  {
      E = E_init*(nrofSymbols-2)/n_SF_PUCCH_s;
613 614 615
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 4 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E);
#endif
616
    }
617

618 619
    if (nrofSymbols > 9)  {
      E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)/n_SF_PUCCH_s):((E_init*(nrofSymbols-4)/n_SF_PUCCH_s));
620 621 622
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 4 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E);
#endif
623 624
    }
  }
625

626
  *M_bit = E;
627
  //int I_seg;
628 629 630
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t\t [nr_uci_encoding] start function with fmt=%d, encoding A=%d bits into M_bit=%d (where nrofSymbols=%d,nrofPRB=%d)\n",fmt,A,*M_bit,nrofSymbols,nrofPRB);
#endif
631

632
  if (A<=11) {
633 634
    // procedure in subclause 6.3.1.2.2 (UCI encoded by channel coding of small block lengths -> subclause 6.3.1.3.2)
    // CRC bits are not attached, and coding small block lengths (subclause 5.3.3)
635 636 637 638 639 640 641 642 643 644 645
    uint64_t b0= encodeSmallBlock((uint16_t*)&payload,A);
    // repetition for rate-matching up to 16 PRB
    b[0] = b0 | (b0<<32);
    b[1] = b[0];
    b[2] = b[0];
    b[3] = b[0];
    b[4] = b[0];
    b[5] = b[0];
    b[6] = b[0];
    b[7] = b[0];
    AssertFatal(nrofPRB<=16,"Number of PRB >16\n");
646
  } else if (A>=12) {
647 648 649
    // Encoder reversal
    payload = reverse_bits(payload, A);

650 651 652 653
    polar_encoder_fast(&payload, b, 0,0,
                       NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, 
                       A, 
                       nrofPRB);
654
  }
655
  
656 657
}
//#if 0
laurent's avatar
laurent committed
658
void nr_generate_pucch2(const PHY_VARS_NR_UE *ue,
659
                        c16_t **txdataF,
laurent's avatar
laurent committed
660 661 662 663 664
                        const NR_DL_FRAME_PARMS *frame_parms,
                        const int16_t amp,
                        const int nr_slot_tx,
                        const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{
665
#ifdef DEBUG_NR_PUCCH_TX
666
  printf("\t [nr_generate_pucch2] start function at slot(nr_slot_tx)=%d  with payload=%lu and nr_bit=%d\n",nr_slot_tx, pucch_pdu->payload, pucch_pdu->n_bit);
667
#endif
668
  // b is the block of bits transmitted on the physical channel after payload coding
669
  uint64_t b[16]; // limit to 1024-bit encoded length
670 671
  // M_bit is the number of bits of block b (payload after encoding)
  uint16_t M_bit;
672 673 674 675 676 677
  nr_uci_encoding(pucch_pdu->payload,
                  pucch_pdu->n_bit,
                  2,0,
                  pucch_pdu->nr_of_symbols,
                  pucch_pdu->prb_size,
                  1,0,0,&b[0],&M_bit);
678 679 680 681 682 683 684 685 686 687 688 689 690
  /*
   * Implementing TS 38.211
   * Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2)
   * The block of bits b(0),..., b(M_bit-1 ), where M_bit is the number of bits transmitted on the physical channel,
   * shall be scrambled prior to modulation,
   * resulting in a block of scrambled bits btilde(0),...,btilde(M_bit-1) according to
   *                     btilde(i)=(b(i)+c(i))mod 2
   * where the scrambling sequence c(i) is given by clause 5.2.1.
   * The scrambling sequence generator shall be initialized with c_init=nRNTI*2^15+n_id
   * n_id = {0,1,...,1023}  equals the higher-layer parameter Data-scrambling-Identity if configured
   * n_id = N_ID_cell       if higher layer parameter not configured
   */
  uint8_t *btilde = malloc(sizeof(int8_t)*M_bit);
Agustin's avatar
Agustin committed
691
  // rnti is given by the C-RNTI
692
  uint16_t rnti=pucch_pdu->rnti;
Agustin's avatar
Agustin committed
693 694 695
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch2] rnti = %d ,\n",rnti);
#endif
696 697 698
  /*
   * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2
   */
699 700 701 702 703 704 705 706 707 708 709 710 711
  nr_pucch2_3_4_scrambling(M_bit, rnti, pucch_pdu->data_scrambling_id, b, btilde);

#ifdef POLAR_CODING_DEBUG
  printf("bt:");
  for (int n = 0; n < M_bit; n++) {
    if (n % 4 == 0) {
      printf(" ");
    }
    printf("%u", btilde[n]);
  }
  printf("\n");
#endif

712 713 714 715 716
  /*
   * Implementing TS 38.211 Subclause 6.3.2.5.2 modulation format 2
   * btilde shall be modulated as described in subclause 5.1 using QPSK
   * resulting in a block of complex-valued modulation symbols d(0),...,d(m_symbol) where m_symbol=M_bit/2
   */
717
  //#define ONE_OVER_SQRT2_S 23171 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
718 719 720 721
  // complex-valued symbol d(0)
  int16_t *d_re = malloc(sizeof(int16_t)*M_bit);
  int16_t *d_im = malloc(sizeof(int16_t)*M_bit);
  uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1;
722 723

  for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3
724 725 726 727
    if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==0)) {
      d_re[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      d_im[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    }
728

729 730 731 732
    if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==1)) {
      d_re[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    }
733

734 735 736 737
    if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==0)) {
      d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      d_im[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    }
738

739 740 741 742 743
    if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==1)) {
      d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    }

744 745 746 747
#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch2] modulation of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]);
#endif
  }
748 749 750 751

  /*
   * Implementing TS 38.211 Subclause 6.3.2.5.3 Mapping to physical resources
   */
752 753
  //int32_t *txptr;
  uint32_t re_offset=0;
754
  uint32_t x1 = 0, x2 = 0, s = 0;
755 756
  int i=0;
  int m=0;
757 758
  uint8_t  startingSymbolIndex = pucch_pdu->start_symbol_index;
  uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
759

760 761
  for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
    // c_init calculation according to TS38.211 subclause
Robert Schmidt's avatar
Robert Schmidt committed
762 763 764 765
    uint64_t temp_x2 = 1ll << 17;
    temp_x2 *= 14UL * nr_slot_tx + l + startingSymbolIndex + 1;
    temp_x2 *= 2UL * pucch_pdu->dmrs_scrambling_id + 1;
    x2 = (temp_x2 + 2UL * pucch_pdu->dmrs_scrambling_id) % (1UL << 31);
766

767 768 769 770 771
    int reset = 1;
    for (int ii=0; ii<=(startingPRB>>2); ii++) {
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
    }
772
    m = 0;
773
    for (int rb=0; rb<pucch_pdu->prb_size; rb++) {
774 775 776 777
      //startingPRB = startingPRB + rb;
      if (((rb+startingPRB) <  (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
      }
778

779 780 781
      if (((rb+startingPRB) >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1)));
      }
782

783 784 785
      if (((rb+startingPRB) <  (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB is lower band
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
      }
786

787 788 789
      if (((rb+startingPRB) >  (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB is upper band
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6;
      }
790

791 792 793
      if (((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB contains DC
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
      }
794

795
      //txptr = &txdataF[0][re_offset];
796
      int k=0;
797
#ifdef DEBUG_NR_PUCCH_TX
798
      int kk=0;
799
#endif
800 801

      for (int n=0; n<12; n++) {
802 803 804 805
        if ((n==6) && ((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) {
          // if number RBs in bandwidth is odd  and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
          re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
        }
806

807 808 809
        if (n%3 != 1) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3
          ((int16_t *)&txdataF[0][re_offset])[0] = d_re[i+k];
          ((int16_t *)&txdataF[0][re_offset])[1] = d_im[i+k];
810
#ifdef DEBUG_NR_PUCCH_TX
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
          printf(
              "\t [nr_generate_pucch2] (n=%d,i=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
              "\tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
              n,
              i,
              amp,
              frame_parms->ofdm_symbol_size,
              frame_parms->N_RB_DL,
              frame_parms->first_carrier_offset,
              i + k,
              re_offset,
              l,
              n,
              ((int16_t *)&txdataF[0][re_offset])[0],
              ((int16_t *)&txdataF[0][re_offset])[1]);
826
#endif
827 828
          k++;
        }
829

830 831 832 833
        if (n%3 == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
          ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)((int32_t)(amp*ONE_OVER_SQRT2*(1-(2*((uint8_t)((s>>(2*m))&1)))))>>15);
          ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)((int32_t)(amp*ONE_OVER_SQRT2*(1-(2*((uint8_t)((s>>((2*m)+1))&1)))))>>15);
          m++;
834
#ifdef DEBUG_NR_PUCCH_TX
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
          printf(
              "\t [nr_generate_pucch2] (n=%d,i=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
              "\tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
              n,
              i,
              amp,
              frame_parms->ofdm_symbol_size,
              frame_parms->N_RB_DL,
              frame_parms->first_carrier_offset,
              i + kk,
              re_offset,
              l,
              n,
              ((int16_t *)&txdataF[0][re_offset])[0],
              ((int16_t *)&txdataF[0][re_offset])[1]);
850
          kk++;
851
#endif
852
        }
853

854 855
        re_offset++;
      }
856

857
      i+=8;
858 859 860 861

      if ((m&((1<<4)-1))==0) {
        s = lte_gold_generic(&x1, &x2, 0);
        m = 0;
862
      }
863 864
    }
  }
865 866 867
  free(d_re);
  free(d_im);
  free(btilde);
868 869
}
//#if 0
laurent's avatar
laurent committed
870
void nr_generate_pucch3_4(const PHY_VARS_NR_UE *ue,
871
                          c16_t **txdataF,
laurent's avatar
laurent committed
872 873 874 875 876
                          const NR_DL_FRAME_PARMS *frame_parms,
                          const int16_t amp,
                          const int nr_slot_tx,
                          const fapi_nr_ul_config_pucch_pdu *pucch_pdu)
{
877
#ifdef DEBUG_NR_PUCCH_TX
878
  printf("\t [nr_generate_pucch3_4] start function at slot(nr_slot_tx)=%d with payload=%lu and nr_bit=%d\n", nr_slot_tx, pucch_pdu->payload, pucch_pdu->n_bit);
879
#endif
880
  // b is the block of bits transmitted on the physical channel after payload coding
laurent's avatar
laurent committed
881
  uint64_t b[16];
882 883 884
  // M_bit is the number of bits of block b (payload after encoding)
  uint16_t M_bit;
  // parameter PUCCH-F4-preDFT-OCC-length set of {2,4} -> to use table -1 or -2
885 886 887 888 889 890 891
  // in format 4, n_SF_PUCCH_s = {2,4}, provided by higher layer parameter PUCCH-F4-preDFT-OCC-length (in format 3 n_SF_PUCCH_s=1)
  uint8_t n_SF_PUCCH_s;
  if (pucch_pdu->format_type == 3)
    n_SF_PUCCH_s = 1;
  else
    n_SF_PUCCH_s = pucch_pdu->pre_dft_occ_len;
  uint8_t is_pi_over_2_bpsk_enabled = pucch_pdu->pi_2bpsk;
892 893 894
  // Intra-slot frequency hopping shall be assumed when the higher-layer parameter intraSlotFrequencyHopping is provided,
  // regardless of whether the frequency-hop distance is zero or not,
  // otherwise no intra-slot frequency hopping shall be assumed
895
  //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers
896
  uint8_t intraSlotFrequencyHopping = 0;
897

898
  if (pucch_pdu->freq_hop_flag) {
899
    intraSlotFrequencyHopping=1;
900 901 902
#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch3_4] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping);
#endif
903
  }
904

905 906 907 908 909 910 911 912 913 914 915 916 917 918
  uint8_t nrofSymbols = pucch_pdu->nr_of_symbols;
  uint16_t nrofPRB = pucch_pdu->prb_size;
  uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
  uint8_t add_dmrs = pucch_pdu->add_dmrs_flag;

  nr_uci_encoding(pucch_pdu->payload,
                  pucch_pdu->n_bit,
                  pucch_pdu->format_type,
                  is_pi_over_2_bpsk_enabled,
                  nrofSymbols,nrofPRB,
                  n_SF_PUCCH_s,
                  intraSlotFrequencyHopping,
                  add_dmrs,
                  &b[0],&M_bit);
919 920 921 922 923 924 925 926 927 928 929 930 931
  /*
   * Implementing TS 38.211
   * Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4)
   * The block of bits b(0),..., b(M_bit-1 ), where M_bit is the number of bits transmitted on the physical channel,
   * shall be scrambled prior to modulation,
   * resulting in a block of scrambled bits btilde(0),...,btilde(M_bit-1) according to
   *                     btilde(i)=(b(i)+c(i))mod 2
   * where the scrambling sequence c(i) is given by clause 5.2.1.
   * The scrambling sequence generator shall be initialized with c_init=nRNTI*2^15+n_id
   * n_id = {0,1,...,1023}  equals the higher-layer parameter Data-scrambling-Identity if configured
   * n_id = N_ID_cell       if higher layer parameter not configured
   */
  uint8_t *btilde = malloc(sizeof(int8_t)*M_bit);
Agustin's avatar
Agustin committed
932
  // rnti is given by the C-RNTI
933
  uint16_t rnti=pucch_pdu->rnti, n_id=0;
Agustin's avatar
Agustin committed
934 935 936
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch3_4] rnti = %d ,\n",rnti);
#endif
937 938 939
  /*
   * Implementing TS 38.211 Subclause 6.3.2.6.1 scrambling formats 3 and 4
   */
Thomas Schlichter's avatar
Thomas Schlichter committed
940
  nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,&b[0],btilde);
941 942 943 944 945 946 947 948 949 950
  /*
   * Implementing TS 38.211 Subclause 6.3.2.6.2 modulation formats 3 and 4
   *
   * Subclause 5.1.1 PI/2-BPSK
   * Subclause 5.1.3 QPSK
   */
  // complex-valued symbol d(0)
  int16_t *d_re = malloc(sizeof(int16_t)*M_bit);
  int16_t *d_im = malloc(sizeof(int16_t)*M_bit);
  uint16_t m_symbol = (M_bit%2==0) ? M_bit/2 : floor(M_bit/2)+1;
951 952

  if (is_pi_over_2_bpsk_enabled == 0) {
953
    // using QPSK if PUCCH format 3,4 and pi/2-BPSK is not configured, according to subclause 6.3.2.6.2
954
    for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3
955 956 957 958
      if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==0)) {
        d_re[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
        d_im[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      }
959

960 961 962 963
      if (((btilde[2*i]&1)==0) && ((btilde[(2*i)+1]&1)==1)) {
        d_re[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
        d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      }
964

965 966 967 968
      if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==0)) {
        d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
        d_im[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      }
969

970 971 972 973
      if (((btilde[2*i]&1)==1) && ((btilde[(2*i)+1]&1)==1)) {
        d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
        d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      }
974 975

#ifdef DEBUG_NR_PUCCH_TX
976
      printf("\t [nr_generate_pucch3_4] modulation QPSK of bit pair btilde(%d,%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[2*i]&1),(btilde[(2*i)+1]&1),m_symbol,i,d_re[i],d_im[i]);
977
#endif
978 979
    }
  }
980 981

  if (is_pi_over_2_bpsk_enabled == 1) {
982 983
    // using PI/2-BPSK if PUCCH format 3,4 and pi/2-BPSK is configured, according to subclause 6.3.2.6.2
    m_symbol = M_bit;
984 985 986

    for (int i=0; i<m_symbol; i++) { // PI/2-BPSK modulation subclause 5.1.1
      if (((btilde[i]&1)==0) && (i%2 == 0)) {
987 988 989
        d_re[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
        d_im[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      }
990 991

      if (((btilde[i]&1)==0) && (i%2 == 1)) {
992 993 994
        d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
        d_im[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      }
995 996

      if (((btilde[i]&1)==1) && (i%2 == 0)) {
997 998 999
        d_re[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
        d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      }
1000 1001

      if (((btilde[i]&1)==1) && (i%2 == 1)) {
1002 1003 1004
        d_re[i] =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
        d_im[i] = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      }
1005 1006

#ifdef DEBUG_NR_PUCCH_TX
1007
      printf("\t [nr_generate_pucch3_4] modulation PI/2-BPSK of bit btilde(%d), m_symbol=%d, d(%d)=(%d,%d)\n",(btilde[i]&1),m_symbol,i,d_re[i],d_im[i]);
1008
#endif
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
    }
  }

  /*
   * Implementing Block-wise spreading subclause 6.3.2.6.3
   */
  // number of PRBs per PUCCH, provided by higher layers parameters PUCCH-F2-number-of-PRBs or PUCCH-F3-number-of-PRBs (for format 4, it is equal to 1)
  // for PUCCH 3 -> nrofPRBs = (2^alpa2 * 3^alpha3 * 5^alpha5)
  // for PUCCH 4 -> nrofPRBs = 1
  // uint8_t nrofPRBs;
  // number of symbols, provided by higher layers parameters PUCCH-F0-F2-number-of-symbols or PUCCH-F1-F3-F4-number-of-symbols
  // uint8_t nrofSymbols;
  // complex-valued symbol d(0)
  int16_t *y_n_re = malloc(sizeof(int16_t)*4*M_bit); // 4 is the maximum number n_SF_PUCCH_s, so is the maximunm size of y_n
  int16_t *y_n_im = malloc(sizeof(int16_t)*4*M_bit);
  // Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1)
  // k={0,..11} n={0,1,2,3}
  // parameter PUCCH-F4-preDFT-OCC-index set of {0,1,2,3} -> n
1027 1028 1029
  uint16_t table_6_3_2_6_3_1_Wn_Re[2][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
    {1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1}
  };
1030 1031
  // Im part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 2 (Table 6.3.2.6.3-1)
  // k={0,..11} n={0,1}
Agustin's avatar
Agustin committed
1032
  uint16_t table_6_3_2_6_3_1_Wn_Im[2][12] = {{0,0,0,0,0,0,0,0,0,0,0,0},
1033 1034
    {0,0,0,0,0,0,0,0,0,0,0,0}
  };
1035 1036
  // Re part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 4 (Table 6.3.2.6.3-2)
  // k={0,..11} n={0,1,2.3}
Agustin's avatar
Agustin committed
1037
  uint16_t table_6_3_2_6_3_2_Wn_Re[4][12] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
1038 1039 1040 1041
    {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0},
    {1, 1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1},
    {1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 0, 0}
  };
1042 1043
  // Im part orthogonal sequences w_n(k) for PUCCH format 4 when N_SF_PUCCH4 = 4 (Table 6.3.2.6.3-2)
  // k={0,..11} n={0,1,2,3}
Agustin's avatar
Agustin committed
1044
  uint16_t table_6_3_2_6_3_2_Wn_Im[4][12] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1045 1046 1047 1048
    {0, 0, 0,-1,-1,-1, 0, 0, 0, 1, 1, 1},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1}
  };
1049 1050

  uint8_t occ_Index  = pucch_pdu->pre_dft_occ_idx;  // higher layer parameter occ-Index
1051 1052

  //occ_Index = 1; //only for testing purposes; to be removed FIXME!!!
1053
  if (pucch_pdu->format_type == 3) { // no block-wise spreading for format 3
1054 1055 1056

    for (int l=0; l < floor(m_symbol/(12*nrofPRB)); l++) {
      for (int k=0; k < (12*nrofPRB); k++) {
1057 1058
        y_n_re[l*(12*nrofPRB)+k] = d_re[l*(12*nrofPRB)+k];
        y_n_im[l*(12*nrofPRB)+k] = d_im[l*(12*nrofPRB)+k];
1059 1060 1061 1062
#ifdef DEBUG_NR_PUCCH_TX
        printf("\t [nr_generate_pucch3_4] block-wise spreading for format 3 (no block-wise spreading): (l,k)=(%d,%d)\ty_n(%d)   = \t(d_re=%d, d_im=%d)\n",
               l,k,l*(12*nrofPRB)+k,d_re[l*(12*nrofPRB)+k],d_im[l*(12*nrofPRB)+k]);
#endif
1063 1064 1065
      }
    }
  }
1066

1067
  if (pucch_pdu->format_type == 4) {
1068
    nrofPRB = 1;
1069 1070 1071 1072

    for (int l=0; l < floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) {
      for (int k=0; k < (12*nrofPRB); k++) {
        if (n_SF_PUCCH_s == 2) {
Agustin's avatar
Agustin committed
1073
          y_n_re[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Re[occ_Index][k])
1074
                                                - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k]));
Agustin's avatar
Agustin committed
1075
          y_n_im[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Re[occ_Index][k])
1076 1077 1078 1079 1080 1081 1082 1083 1084
                                                + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_1_Wn_Im[occ_Index][k]));
#ifdef DEBUG_NR_PUCCH_TX
          printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 2) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d)   = \t(d_re=%d, d_im=%d)\n",
                 occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]);
          //            printf("\t\t d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]);
          //            printf("\t\t d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] = %d\n",d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)]);
          //            printf("\t\t table_6_3_2_6_3_1_Wn_Re[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Re[occ_Index][k]);
          //            printf("\t\t table_6_3_2_6_3_1_Wn_Im[%d][%d] = %d\n",occ_Index,k,table_6_3_2_6_3_1_Wn_Im[occ_Index][k]);
#endif
1085
        }
1086 1087

        if (n_SF_PUCCH_s == 4) {
Agustin's avatar
Agustin committed
1088
          y_n_re[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Re[occ_Index][k])
1089
                                                - ((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k]));
Agustin's avatar
Agustin committed
1090
          y_n_im[l*(12*nrofPRB)+k] = (uint16_t)(((uint32_t)d_im[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Re[occ_Index][k])
1091 1092 1093 1094 1095
                                                + ((uint32_t)d_re[l*(12*nrofPRB/n_SF_PUCCH_s)+k%(12*nrofPRB/n_SF_PUCCH_s)] * table_6_3_2_6_3_2_Wn_Im[occ_Index][k]));
#ifdef DEBUG_NR_PUCCH_TX
          printf("\t [nr_generate_pucch3_4] block-wise spreading for format 4 (n_SF_PUCCH_s 4) (occ_Index=%d): (l,k)=(%d,%d)\ty_n(%d)   = \t(d_re=%d, d_im=%d)\n",
                 occ_Index,l,k,l*(12*nrofPRB)+k,y_n_re[l*(12*nrofPRB)+k],y_n_im[l*(12*nrofPRB)+k]);
#endif
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
        }
      }
    }
  }

  /*
   * Implementing Transform pre-coding subclause 6.3.2.6.4
   */
  int16_t *z_re = malloc(sizeof(int16_t)*4*M_bit); // 4 is the maximum number n_SF_PUCCH_s
  int16_t *z_im = malloc(sizeof(int16_t)*4*M_bit);
1106 1107
#define M_PI 3.14159265358979323846 // pi

1108
  //int16_t inv_sqrt_nrofPRBs = (int16_t)round(32767/sqrt(12*nrofPRB));
1109 1110
  for (int l=0; l<floor((n_SF_PUCCH_s*m_symbol)/(12*nrofPRB)); l++) {
    for (int k=0; k<(12*nrofPRB); k++) {
1111 1112
      z_re[l*(12*nrofPRB)+k] = 0;
      z_im[l*(12*nrofPRB)+k] = 0;
1113 1114 1115 1116

      //      int16_t z_re_tmp[240] = {0};
      //      int16_t z_im_tmp[240] = {0};
      for (int m=0; m<(12*nrofPRB); m++) {
1117
        //z_re[l*(12*nrofPRB)+k] = y_n_re[l*(12*nrofPRB)+m] * (int16_t)(round(32767*cos((2*M_PI*m*k)/(12*nrofPRB))));
1118 1119 1120 1121
        //        z_re_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15)
        //                + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15);
        //        z_im_tmp[m] = (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15)
        //                - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15);
1122
        z_re[l*(12*nrofPRB)+k] = z_re[l*(12*nrofPRB)+k]
1123 1124
                                 + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15)
                                              + (((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15);
1125
        z_im[l*(12*nrofPRB)+k] = z_im[l*(12*nrofPRB)+k]
1126 1127 1128 1129 1130 1131 1132 1133
                                 + (int16_t)(((int32_t)round(32767/sqrt(12*nrofPRB))*(int16_t)((((int32_t)y_n_im[l*(12*nrofPRB)+m] * (int16_t)round(32767 * cos(2*M_PI*m*k/(12*nrofPRB))))>>15)
                                              - (((int32_t)y_n_re[l*(12*nrofPRB)+m] * (int16_t)round(32767 * sin(2*M_PI*m*k/(12*nrofPRB))))>>15)))>>15);
#ifdef DEBUG_NR_PUCCH_TX
        //        printf("\t\t z_re_tmp[%d] = %d\n",m,z_re_tmp[m]);
        //        printf("\t\t z_im_tmp[%d] = %d\n",m,z_im_tmp[m]);
        //          printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k,m)=(%d,%d,%d)\tz(%d)   = \t(%d, %d)\n",
        //                  l,k,m,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]);
#endif
1134
      }
1135 1136 1137 1138 1139

#ifdef DEBUG_NR_PUCCH_TX
      printf("\t [nr_generate_pucch3_4] transform precoding for formats 3 and 4: (l,k)=(%d,%d)\tz(%d)   = \t(%d, %d)\n",
             l,k,l*(12*nrofPRB)+k,z_re[l*(12*nrofPRB)+k],z_im[l*(12*nrofPRB)+k]);
#endif
1140 1141 1142 1143
    }
  }

  /*
1144
   * Implementing TS 38.211 Subclauses 6.3.2.5.3 and 6.3.2.6.5 Mapping to physical resources
1145 1146
   */
  // the value of u,v (delta always 0 for PUCCH) has to be calculated according to TS 38.211 Subclause 6.3.2.2.1
yilmazt's avatar
yilmazt committed
1147
  uint8_t u=0,v=0;//,delta=0;
1148 1149 1150 1151 1152 1153 1154
  // if frequency hopping is disabled, intraSlotFrequencyHopping is not provided
  //              n_hop = 0
  // if frequency hopping is enabled,  intraSlotFrequencyHopping is     provided
  //              n_hop = 0 for first hop
  //              n_hop = 1 for second hop
  uint8_t n_hop = 0;
  // lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
yilmazt's avatar
yilmazt committed
1155
  //uint8_t lnormal = 0 ;
1156
  // lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
yilmazt's avatar
yilmazt committed
1157
  //uint8_t lprime = startingSymbolIndex;
1158 1159 1160
  // m0 is the cyclic shift index calculated depending on the Orthogonal sequence index n, according to table 6.4.1.3.3.1-1 from TS 38.211 subclause 6.4.1.3.3.1
  uint8_t m0;
  uint8_t mcs=0;
1161

1162
  if (pucch_pdu->format_type == 3) m0 = 0;
1163

1164
  if (pucch_pdu->format_type == 4) {
1165 1166 1167
    if (n_SF_PUCCH_s == 2) {
      m0 = (occ_Index == 0) ? 0 : 6;
    }
1168

1169 1170 1171 1172
    if (n_SF_PUCCH_s == 4) {
      m0 = (occ_Index == 3) ? 9 : ((occ_Index == 2) ? 3 : ((occ_Index == 1) ? 6 : 0));
    }
  }
1173

1174 1175 1176 1177
  double alpha;
  uint8_t N_ZC = 12*nrofPRB;
  int16_t *r_u_v_base_re        = malloc(sizeof(int16_t)*12*nrofPRB);
  int16_t *r_u_v_base_im        = malloc(sizeof(int16_t)*12*nrofPRB);
yilmazt's avatar
yilmazt committed
1178 1179
  //int16_t *r_u_v_alpha_delta_re = malloc(sizeof(int16_t)*12*nrofPRB);
  //int16_t *r_u_v_alpha_delta_im = malloc(sizeof(int16_t)*12*nrofPRB);
1180
  // Next we proceed to mapping to physical resources according to TS 38.211, subclause 6.3.2.6.5 dor PUCCH formats 3 and 4 and subclause 6.4.1.3.3.2 for DM-RS
1181 1182
  //int32_t *txptr;
  uint32_t re_offset=0;
yilmazt's avatar
yilmazt committed
1183
  //uint32_t x1, x2, s=0;
1184 1185
  // intraSlotFrequencyHopping
  // uint8_t intraSlotFrequencyHopping = 0;
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
  uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] = {
    {(intraSlotFrequencyHopping==0)?0:1,(intraSlotFrequencyHopping==0)?1:0,(intraSlotFrequencyHopping==0)?0:1,0,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 4
    {1,0,0,1,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 5
    {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 6
    {0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 7
    {0,1,0,0,0,1,0,0,0,0,0,0,0,0}, // PUCCH length = 8
    {0,1,0,0,0,0,1,0,0,0,0,0,0,0}, // PUCCH length = 9
    {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,0,0,0}, // PUCCH length = 10
    {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0,0}, // PUCCH length = 11
    {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0}, // PUCCH length = 12
    {0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0}, // PUCCH length = 13
    {0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0}  // PUCCH length = 14
1198 1199
  };
  uint16_t k=0;
1200

1201
  for (int l=0; l<nrofSymbols; l++) {
1202 1203
    if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop

1204 1205
    pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
    nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,nr_slot_tx,&u,&v); // calculating u and v value
1206 1207 1208 1209

    // Next we proceed to calculate base sequence for DM-RS signal, according to TS 38.211 subclause 6.4.1.33
    if (nrofPRB >= 3) { // TS 38.211 subclause 5.2.2.1 (Base sequences of length 36 or larger) applies
      int i = 4;
1210

1211
      while (list_of_prime_numbers[i] < (12*nrofPRB)) i++;
1212

1213 1214 1215 1216
      N_ZC = list_of_prime_numbers[i+1]; // N_ZC is given by the largest prime number such that N_ZC < (12*nrofPRB)
      double q_base = (N_ZC*(u+1))/31;
      int8_t q = (uint8_t)floor(q_base + (1/2));
      q = ((uint8_t)floor(2*q_base)%2 == 0 ? q+v : q-v);
1217 1218

      for (int n=0; n<(12*nrofPRB); n++) {
1219 1220
        r_u_v_base_re[n] =  (int16_t)(((int32_t)amp*(int16_t)(32767*cos(M_PI*q*(n%N_ZC)*((n%N_ZC)+1)/N_ZC)))>>15);
        r_u_v_base_im[n] = -(int16_t)(((int32_t)amp*(int16_t)(32767*sin(M_PI*q*(n%N_ZC)*((n%N_ZC)+1)/N_ZC)))>>15);
1221 1222 1223 1224
#ifdef DEBUG_NR_PUCCH_TX
        printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d >= 3: r_u_v_base[n=%d]=(%d,%d)\n",
               nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]);
#endif
1225 1226
      }
    }
1227

1228
    if (nrofPRB == 2) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-4) applies
1229
      for (int n=0; n<(12*nrofPRB); n++) {
1230 1231
        r_u_v_base_re[n] =  (int16_t)(((int32_t)amp*table_5_2_2_2_4_Re[u][n])>>15);
        r_u_v_base_im[n] =  (int16_t)(((int32_t)amp*table_5_2_2_2_4_Im[u][n])>>15);
1232 1233 1234 1235
#ifdef DEBUG_NR_PUCCH_TX
        printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 2: r_u_v_base[n=%d]=(%d,%d)\n",
               nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]);
#endif
1236 1237
      }
    }
1238

1239
    if (nrofPRB == 1) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-2) applies
1240
      for (int n=0; n<(12*nrofPRB); n++) {
1241 1242
        r_u_v_base_re[n] =  (int16_t)(((int32_t)amp*table_5_2_2_2_2_Re[u][n])>>15);
        r_u_v_base_im[n] =  (int16_t)(((int32_t)amp*table_5_2_2_2_2_Im[u][n])>>15);
1243 1244 1245 1246
#ifdef DEBUG_NR_PUCCH_TX
        printf("\t [nr_generate_pucch3_4] generation DM-RS base sequence when nrofPRB=%d == 1: r_u_v_base[n=%d]=(%d,%d)\n",
               nrofPRB,n,r_u_v_base_re[n],r_u_v_base_im[n]);
#endif
1247 1248 1249
      }
    }

1250
    uint8_t  startingSymbolIndex = pucch_pdu->start_symbol_index;
1251
    uint16_t j=0;
1252
    alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,m0,mcs,l,startingSymbolIndex,nr_slot_tx);
1253 1254

    for (int rb=0; rb<nrofPRB; rb++) {
1255
      if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB
1256
        startingPRB = startingPRB + pucch_pdu->second_hop_prb;
1257
      }
1258

1259 1260 1261
      //startingPRB = startingPRB + rb;
      if (((rb+startingPRB) <  (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
1262 1263 1264
#ifdef DEBUG_NR_PUCCH_TX
        printf("1   ");
#endif
1265
      }
1266

1267 1268
      if (((rb+startingPRB) >= (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is upper band
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1)));
1269 1270 1271
#ifdef DEBUG_NR_PUCCH_TX
        printf("2   ");
#endif
1272
      }
1273

1274 1275
      if (((rb+startingPRB) <  (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB is lower band
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
1276 1277 1278
#ifdef DEBUG_NR_PUCCH_TX
        printf("3   ");
#endif
1279
      }
1280

1281 1282
      if (((rb+startingPRB) >  (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB is upper band
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*((rb+startingPRB)-(frame_parms->N_RB_DL>>1))) + 6;
1283 1284 1285
#ifdef DEBUG_NR_PUCCH_TX
        printf("4   ");
#endif
1286
      }
1287

1288 1289
      if (((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd  and current PRB contains DC
        re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(rb+startingPRB)) + frame_parms->first_carrier_offset;
1290 1291 1292
#ifdef DEBUG_NR_PUCCH_TX
        printf("5   ");
#endif
1293
      }
1294 1295

#ifdef DEBUG_NR_PUCCH_TX
1296
      printf("re_offset=%u,(rb+startingPRB)=%d\n",re_offset,(rb+startingPRB));
1297 1298
#endif

1299
      //txptr = &txdataF[0][re_offset];
1300
      for (int n=0; n<12; n++) {
1301 1302 1303 1304
        if ((n==6) && ((rb+startingPRB) == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) {
          // if number RBs in bandwidth is odd  and current PRB contains DC, we need to recalculate the offset when n=6 (for second half PRB)
          re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size);
        }
1305

1306 1307 1308
        if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 0) { // mapping PUCCH according to TS38.211 subclause 6.3.2.5.3
          ((int16_t *)&txdataF[0][re_offset])[0] = z_re[n+k];
          ((int16_t *)&txdataF[0][re_offset])[1] = z_im[n+k];
1309
#ifdef DEBUG_NR_PUCCH_TX
1310
          printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(z(l=%d,n=%d)=(%d,%d))\n",
1311 1312 1313
                 l,rb,n,k,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+k,re_offset,
                 l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
#endif
1314
        }
1315

1316 1317
        if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
          ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)((((int32_t)(32767*cos(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15)
1318
              - (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15));
1319
          ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)((((int32_t)(32767*cos(alpha*((n+j)%N_ZC)))*r_u_v_base_im[n+j])>>15)
1320 1321
              + (((int32_t)(32767*sin(alpha*((n+j)%N_ZC)))*r_u_v_base_re[n+j])>>15));
#ifdef DEBUG_NR_PUCCH_TX
1322
          printf("\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(r_u_v(l=%d,n=%d)=(%d,%d))\n",
1323 1324 1325
                 l,rb,n,j,amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,n+j,re_offset,
                 l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
#endif
1326
        }
1327

1328 1329
        re_offset++;
      }
1330

1331
      if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 0) k+=12;
1332

1333 1334 1335
      if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) j+=12;
    }
  }
1336 1337 1338
  free(z_re);
  free(z_im);
  free(btilde);
1339
}