pucch_nr.c 90.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 "LAYER2/MAC/extern.h"
38
#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
39
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
40

41
42
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
43
44

#include "T.h"
45
#ifdef NR_UNIT_TEST
46
47
48
  #define DEBUG_PUCCH_TX
  #define DEBUG_NR_PUCCH_TX
#endif
49
//#define ONE_OVER_SQRT2 23170 // 32767/sqrt(2) = 23170 (ONE_OVER_SQRT2)
50

51
52
53
54
55
56
void nr_group_sequence_hopping (pucch_GroupHopping_t PUCCH_GroupHopping,
  				uint32_t n_id,
  				uint8_t n_hop,
  				int nr_tti_tx,
  				uint8_t *u,
  				uint8_t *v) {
57
58
59
60
61
62
63
64
65
66
67
68
  /*
   * Implements TS 38.211 subclause 6.3.2.2.1 Group and sequence hopping
   * The following variables are set by higher layers:
   *    - PUCCH_GroupHopping:
   *    - n_id: higher-layer parameter hoppingId
   *    - n_hop: frequency hopping index
   *             if intra-slot frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping
   *                n_hop=0
   *             if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping
   *                n_hop=0 for the first hop
   *                n_hop=1 for the second hop
   */
69
  // depending on the value of the PUCCH_GroupHopping, we will obtain different values for u,v
70
  //pucch_GroupHopping_t PUCCH_GroupHopping = ue->pucch_config_common_nr->pucch_GroupHopping; // from higher layers FIXME!!!
71
72
73
74
  // n_id defined as per TS 38.211 subclause 6.3.2.2.1 (is given by the higher-layer parameter hoppingId)
  // it is hoppingId from PUCCH-ConfigCommon:
  // Cell-Specific scrambling ID for group hoppping and sequence hopping if enabled
  // Corresponds to L1 parameter 'HoppingID' (see 38.211, section 6.3.2.2) BIT STRING (SIZE (10))
75
  //uint16_t n_id = ue->pucch_config_common_nr->hoppingId; // from higher layers FIXME!!!
76
77
78
79
80
81
#ifdef DEBUG_NR_PUCCH_TX
  // initialization to be removed
  PUCCH_GroupHopping=neither;
  n_id=10;
  printf("\t\t [nr_group_sequence_hopping] initialization PUCCH_GroupHopping=%d, n_id=%d -> variable initializations TO BE REMOVED\n",PUCCH_GroupHopping,n_id);
#endif
82
83
84
  uint8_t f_ss=0,f_gh=0;
  *u=0;
  *v=0;
85
86
  uint32_t c_init = 0; 
  uint32_t x1,s; // TS 38.211 Subclause 5.2.1
87
88
  int l = 32, minShift = ((2*nr_tti_tx+n_hop)<<3);
  int tmpShift =0;
89
90
91
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t\t [nr_group_sequence_hopping] calculating u,v -> ");
#endif
92

93
  if (PUCCH_GroupHopping == neither) { // PUCCH_GroupHopping 'neither'
94
95
    f_ss = n_id%30;
  }
96
97

  if (PUCCH_GroupHopping == enable) { // PUCCH_GroupHopping 'enabled'
98
    c_init = floor(n_id/30); // we initialize c_init to calculate u,v according to 6.3.2.2.1 of 38.211
99
    s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
100
101
102
103
104
105
106
107
108
    for (int m=0; m<8; m++) {
      while(minShift >= l) {
        s = lte_gold_generic(&x1, &c_init, 0);
        l = l+32;
      }

      tmpShift = (minShift&((1<<5)-1)); //minShift%32;
      f_gh = f_gh + ((1<<m)*((uint8_t)((s>>tmpShift)&1)));
      minShift ++;
109
    }
110

111
    f_gh = f_gh%30;
112
113
114
115
116
117
    f_ss = n_id%30;
    /*    for (int m=0; m<8; m++){
          f_gh = f_gh + ((1<<m)*((uint8_t)((s>>(8*(2*nr_tti_tx+n_hop)+m))&1))); // Not sure we have to use nr_tti_tx FIXME!!!
        }
        f_gh = f_gh%30;
        f_ss = n_id%30;*/
118
  }
119
120

  if (PUCCH_GroupHopping == disable) { // PUCCH_GroupHopping 'disabled'
121
    c_init = (1<<5)*floor(n_id/30)+(n_id%30); // we initialize c_init to calculate u,v
122
    s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
123
    f_ss = n_id%30;
124
    l = 32, minShift = (2*nr_tti_tx+n_hop);
125
126
127
128

    while(minShift >= l) {
      s = lte_gold_generic(&x1, &c_init, 0);
      l = l+32;
129
    }
130

131
132
    tmpShift = (minShift&((1<<5)-1)); //minShift%32;
    *v = (uint8_t)((s>>tmpShift)&1);
133
    //    *v = (uint8_t)((s>>(2*nr_tti_tx+n_hop))&1); // Not sure we have to use nr_tti_tx FIXME!!!
134
  }
135

136
  *u = (f_gh+f_ss)%30;
137
138
139
#ifdef DEBUG_NR_PUCCH_TX
  printf("%d,%d\n",*u,*v);
#endif
140
}
141

142
double nr_cyclic_shift_hopping(uint32_t n_id,
143
144
145
146
                               uint8_t m0,
                               uint8_t mcs,
                               uint8_t lnormal,
                               uint8_t lprime,
147
                               int nr_tti_tx) {
148
149
150
151
152
153
154
155
  /*
   * Implements TS 38.211 subclause 6.3.2.2.2 Cyclic shift hopping
   *     - n_id: higher-layer parameter hoppingId
   *     - m0: provided by higher layer parameter PUCCH-F0-F1-initial-cyclic-shift of PUCCH-F0-resource-config
   *     - mcs: mcs=0 except for PUCCH format 0 when it depends on information to be transmitted according to TS 38.213 subclause 9.2
   *     - lnormal: lnormal is the OFDM symbol number in the PUCCH transmission where l=0 corresponds to the first OFDM symbol of the PUCCH transmission
   *     - lprime: 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]
   */
156
157
  // alpha_init initialized to 2*PI/12=0.5235987756
  double alpha = 0.5235987756;
158
  uint32_t c_init = n_id; // we initialize c_init again to calculate n_cs
159
160
161
162
163
#ifdef DEBUG_NR_PUCCH_TX
  // initialization to be remo.ved
  c_init=10;
  printf("\t\t [nr_cyclic_shift_hopping] initialization c_init=%d -> variable initialization TO BE REMOVED\n",c_init);
#endif
164
165
  uint32_t x1,s = lte_gold_generic(&x1, &c_init, 1); // TS 38.211 Subclause 5.2.1
  uint8_t n_cs=0;
166
167
168
169
170
  int l = 32, minShift = (14*8*nr_tti_tx )+ 8*(lnormal+lprime);
  int tmpShift =0;
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t\t [nr_cyclic_shift_hopping] calculating alpha (cyclic shift) using c_init=%d -> \n",c_init);
#endif
171
172
173
174
175
176
177
178
179
180

  for (int m=0; m<8; m++) {
    while(minShift >= l) {
      s = lte_gold_generic(&x1, &c_init, 0);
      l = l+32;
    }

    tmpShift = (minShift&((1<<5)-1)); //minShift%32;
    minShift ++;
    n_cs = n_cs+((1<<m)*((uint8_t)((s>>tmpShift)&1)));
181
    // calculating n_cs (Not sure we have to use nr_tti_tx FIXME!!!)
182
    // n_cs = n_cs+((1<<m)*((uint8_t)((s>>((14*8*nr_tti_tx) + 8*(lnormal+lprime) + m))&1)));
183
  }
184

185
  alpha = (alpha * (double)((m0+mcs+n_cs)%12));
186
187
188
#ifdef DEBUG_NR_PUCCH_TX
  printf("n_cs=%d -> %lf\n",n_cs,alpha);
#endif
189
190
  return(alpha);
}
191
192
void nr_generate_pucch0(PHY_VARS_NR_UE *ue,
                        int32_t **txdataF,
193
194
195
                        NR_DL_FRAME_PARMS *frame_parms,
                        PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
                        int16_t amp,
196
                        int nr_tti_tx,
197
                        uint8_t m0,
198
199
200
                        uint8_t mcs,
                        uint8_t nrofSymbols,
                        uint8_t startingSymbolIndex,
201
                        uint16_t startingPRB) {
202
203
204
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch0] start function at slot(nr_tti_tx)=%d\n",nr_tti_tx);
#endif
205
206
207
208
  /*
   * Implement TS 38.211 Subclause 6.3.2.3.1 Sequence generation
   *
   */
209
210
211
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch0] sequence generation\n");
#endif
212
213
214
215
216
217
  /*
   * 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
218
  //uint8_t lnormal;
219
  // 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
220
  //uint8_t lprime;
221
222
223
224
225
226
227
228
229
230
231
232
  // 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
yilmazt's avatar
yilmazt committed
233
  uint8_t u=0,v=0;//,delta=0;
234
235
236
237
238
239
  // if frequency hopping is disabled by the higher-layer parameter PUCCH-frequency-hopping
  //              n_hop = 0
  // if frequency hopping is enabled by the higher-layer parameter PUCCH-frequency-hopping
  //              n_hop = 0 for first hop
  //              n_hop = 1 for second hop
  uint8_t n_hop = 0;
240
  //uint8_t PUCCH_Frequency_Hopping; // from higher layers FIXME!!
Jacques's avatar
Jacques committed
241
#ifdef DEBUG_NR_PUCCH_TX
242
  printf("\t [nr_generate_pucch0] sequence generation: variable initialization for test\n");
Jacques's avatar
Jacques committed
243
#endif
244
245
  // x_n contains the sequence r_u_v_alpha_delta(n)
  int16_t x_n_re[24],x_n_im[24];
246

247
  // we proceed to calculate alpha according to TS 38.211 Subclause 6.3.2.2.2
248
  for (int l=0; l<nrofSymbols; l++) {
249
    // if frequency hopping is enabled n_hop = 1 for second hop. Not sure frequency hopping concerns format 0. FIXME!!!
250
    // if ((PUCCH_Frequency_Hopping == 1)&&(l == (nrofSymbols-1))) n_hop = 1;
251
252
    nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_tti_tx,&u,&v); // calculating u and v value
    alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,l,startingSymbolIndex,nr_tti_tx);
253
254
255
256
257
#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch0] sequence generation \tu=%d \tv=%d \talpha=%lf \t(for symbol l=%d)\n",u,v,alpha,l);
#endif

    for (int n=0; n<12; n++) {
258
      x_n_re[(12*l)+n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Re[u][n])>>15)
259
                                    - (((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
260
      x_n_im[(12*l)+n] = (int16_t)(((((int32_t)(round(32767*cos(alpha*n))) * table_5_2_2_2_2_Im[u][n])>>15)
261
262
263
264
265
                                    + (((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
#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",
             u,v,alpha,l,n,x_n_re[(12*l)+n],x_n_im[(12*l)+n]);
#endif
266
267
    }
  }
268

269
270
271
  /*
   * Implementing TS 38.211 Subclause 6.3.2.3.2 Mapping to physical resources FIXME!
   */
272
273
  //int32_t *txptr;
  uint32_t re_offset=0;
274

275
276
277
278
  for (int l=0; l<nrofSymbols; l++) {
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }
279

280
281
282
    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)));
    }
283

284
285
286
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }
287

288
289
290
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6;
    }
291

292
293
294
    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;
    }
295

296
    //txptr = &txdataF[0][re_offset];
297
    for (int n=0; n<12; n++) {
298
299
300
301
      if ((n==6) && (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);
      }
302

303
304
305
306
307
      ((int16_t *)&txdataF[0][re_offset])[0] = (int16_t)(((int32_t)(amp) * x_n_re[(12*l)+n])>>15);
      ((int16_t *)&txdataF[0][re_offset])[1] = (int16_t)(((int32_t)(amp) * x_n_im[(12*l)+n])>>15);
      //((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];
308
309
310
311
312
#ifdef DEBUG_NR_PUCCH_TX
      printf("\t [nr_generate_pucch0] mapping to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \ttxptr(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n",
             amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,re_offset,
             l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
#endif
313
314
315
316
      re_offset++;
    }
  }
}
317

318
319
void nr_generate_pucch1(PHY_VARS_NR_UE *ue,
                        int32_t **txdataF,
320
321
322
323
                        NR_DL_FRAME_PARMS *frame_parms,
                        PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
                        uint64_t payload,
                        int16_t amp,
324
                        int nr_tti_tx,
325
                        uint8_t m0,
326
327
                        uint8_t nrofSymbols,
                        uint8_t startingSymbolIndex,
328
329
                        uint16_t startingPRB,
                        uint16_t startingPRB_intraSlotHopping,
330
331
332
                        uint8_t timeDomainOCC,
                        uint8_t nr_bit) {
#ifdef DEBUG_NR_PUCCH_TX
333
  printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%d m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n",
334
         nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit);
335
336
#endif
  /*
337
338
339
340
   * 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):
341
  int16_t d_re=0, d_im=0;
342

343
344
345
346
  if (nr_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2
    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);
  }
347

348
349
350
351
352
  if (nr_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2
    if (((payload&1)==0) && (((payload>>1)&1)==0)) {
      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);
    }
353

354
355
356
357
    if (((payload&1)==0) && (((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);
    }
358

359
360
361
362
    if (((payload&1)==1) && (((payload>>1)&1)==0)) {
      d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      d_im =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    }
363

364
365
366
367
368
369
    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);
    }
  }

370
371
372
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch1] sequence modulation: payload=%x \tde_re=%d \tde_im=%d\n",payload,d_re,d_im);
#endif
373
374
375
376
377
378
  /*
   * 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
379
  //uint8_t lnormal = 0 ;
380
381
382
383
384
385
386
  // 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;
  // mcs = 0 except for PUCCH format 0
  uint8_t mcs=0;
  // 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];
387
  /*
388
389
390
391
392
393
394
395
   * 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
396
  uint8_t u=0,v=0;//,delta=0;
397
398
399
400
401
402
403
404
405
406
407
  // 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;
408
409

  if (startingPRB != startingPRB_intraSlotHopping) {
410
411
    intraSlotFrequencyHopping=1;
  }
412

413
414
415
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping = %d \n",intraSlotFrequencyHopping);
#endif
416
417
418
  /*
   * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources
   */
419
420
  //int32_t *txptr;
  uint32_t re_offset=0;
421
  int i=0;
422
#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
423
424
425
426
  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];

  for (int l=0; l<nrofSymbols; l++) {
427
428
429
430
#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch1] for symbol l=%d, lprime=%d\n",
           l,lprime);
#endif
431
432
    // y_n contains the complex value d multiplied by the sequence r_u_v
    int16_t y_n_re[12],y_n_im[12];
433

434
    if ((intraSlotFrequencyHopping == 1) && (l >= (int)floor(nrofSymbols/2))) n_hop = 1; // n_hop = 1 for second hop
435
436
437
438
439

#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n",
           n_hop,nr_tti_tx);
#endif
440
441
    nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_tti_tx,&u,&v); // calculating u and v value
    alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,l,lprime,nr_tti_tx);
442
443

    for (int n=0; n<12; n++) {
444
      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)
445
                                           - (((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
446
      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)
447
                                           + (((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
448
      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)
449
                                     - (((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
450
      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)
451
                                     + (((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
452
453
      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);
454
455
      // 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)
456
                                           - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n)
457
      y_n_im[n]               = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15)
458
459
460
461
462
                                           + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n)
#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
463
    }
464

465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
    /*
     * 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;
490

491
    if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled
492
493
494
495
#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
496
497
498
499
      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)
500
501
502
503
504
505
506
#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++) {
507
          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)
508
              - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15));
509
          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)
510
511
512
513
514
515
516
517
              + (((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
518
519
        }
      }
520
521
522

      for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
        for (int n=0; n<12 ; n++) {
523
          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_1][w_index][m])*r_u_v_alpha_delta_dmrs_re[n])>>15)
524
              - (((int32_t)(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])>>15));
525
          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_1][w_index][m])*r_u_v_alpha_delta_dmrs_im[n])>>15)
526
527
528
529
530
531
532
533
              + (((int32_t)(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])>>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],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
534
535
536
        }
      }
    }
537

538
    if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled
539
540
541
542
#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
543
544
545
546
      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)
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
#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 (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));
#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]);
566
#endif
567
            }
568
          }
569
570
571
572
573
574
575
576
577
578
579
580
581

          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_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_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_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_1][w_index][m])*r_u_v_alpha_delta_dmrs_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],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]);
582
#endif
583
            }
584
          }
585
586
587

          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)
588
        }
589
      }
590
    }
591

592
593
594
    if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB
      startingPRB = startingPRB + startingPRB_intraSlotHopping;
    }
595

596
597
598
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }
599

600
601
602
    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)));
    }
603

604
605
606
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }
607

608
609
610
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6;
    }
611

612
613
614
615
    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;
    }

616
    //txptr = &txdataF[0][re_offset];
617
    for (int n=0; n<12; n++) {
618
619
620
621
      if ((n==6) && (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);
      }
622

623
624
625
      if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1
        ((int16_t *)&txdataF[0][re_offset])[0] = z_re[i+n];
        ((int16_t *)&txdataF[0][re_offset])[1] = z_im[i+n];
626
627
628
629
630
#ifdef DEBUG_NR_PUCCH_TX
        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(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n",
               amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset,
               l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
#endif
631
      }
632

633
634
635
      if (l%2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1
        ((int16_t *)&txdataF[0][re_offset])[0] = z_dmrs_re[i+n];
        ((int16_t *)&txdataF[0][re_offset])[1] = z_dmrs_im[i+n];
636
637
638
639
640
#ifdef DEBUG_NR_PUCCH_TX
        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(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n",
               amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset,
               l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
#endif
641
      }
642

643
644
      re_offset++;
    }
645

646
647
648
649
650
651
    if (l%2 == 1) i+=12;
  }
}

#if 0
void nr_generate_pucch1_old(PHY_VARS_NR_UE *ue,
652
653
654
655
656
657
658
659
660
661
662
663
664
                            int32_t **txdataF,
                            NR_DL_FRAME_PARMS *frame_parms,
                            PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
                            uint64_t payload,
                            int16_t amp,
                            int nr_tti_tx,
                            uint8_t m0,
                            uint8_t nrofSymbols,
                            uint8_t startingSymbolIndex,
                            uint16_t startingPRB,
                            uint16_t startingPRB_intraSlotHopping,
                            uint8_t timeDomainOCC,
                            uint8_t nr_bit) {
665
666
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%d m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n",
667
         nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit);
668
#endif
669
670
671
672
673
674
  /*
   * 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):
  int16_t d_re, d_im;
675

676
  if (nr_bit == 1) { // using BPSK if M_bit=1 according to TC 38.211 Subclause 5.1.2
677
678
679
    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);
  }
680

681
  if (nr_bit == 2) { // using QPSK if M_bit=2 according to TC 38.211 Subclause 5.1.2
682
683
684
685
    if (((payload&1)==0) && (((payload>>1)&1)==0)) {
      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);
    }
686

687
688
689
690
    if (((payload&1)==0) && (((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);
    }
691

692
693
694
695
    if (((payload&1)==1) && (((payload>>1)&1)==0)) {
      d_re = -(int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
      d_im =  (int16_t)(((int32_t)amp*ONE_OVER_SQRT2)>>15);
    }
696

697
698
699
700
701
702
    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);
    }
  }

703
704
705
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch1] sequence modulation: payload=%x \tde_re=%d \tde_im=%d\n",payload,d_re,d_im);
#endif
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
  /*
   * 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
  uint8_t lnormal = 0 ;
  // 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;
  // mcs = 0 except for PUCCH format 0
  uint8_t mcs=0;
  // r_u_v_alpha_delta_re and r_u_v_alpha_delta_im tables containing the sequence for the DM-RS.
  // When they are multiplied by d(0), they become the sequence y(n) for the PUCCH
  int16_t r_u_v_alpha_delta_re[12],r_u_v_alpha_delta_im[12];
  /*
   * 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
  uint8_t u=0,v=0,delta=0;
  // 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
739
  //uint8_t PUCCH_Frequency_Hopping = 0 ; // from higher layers
740
  uint8_t intraSlotFrequencyHopping = 0;
741
742

  if (startingPRB != startingPRB_intraSlotHopping) {
743
    intraSlotFrequencyHopping=1;
744
745
746
#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch1] intraSlotFrequencyHopping=%d \n",intraSlotFrequencyHopping);
#endif
747
748
749
750
751
    // n_hop = 1 for second hop;
    // FIXME
    // When hopping will be activated we have to implement this function differently as PUCH signal generation depends on n_hop value for u,v calculation
  }

752
753
  // y_n contains the complex value d multiplied by the sequence r_u_v
  int16_t y_n_re[12],y_n_im[12];
754
755
756
757
#ifdef DEBUG_NR_PUCCH_TX
  printf("\t [nr_generate_pucch1] entering function nr_group_sequence_hopping with n_hop=%d, nr_tti_tx=%d\n",
         n_hop,nr_tti_tx);
#endif
758
759
  nr_group_sequence_hopping(ue->pucch_config_common_nr->pucch_GroupHopping,ue->pucch_config_common_nr->hoppingId,n_hop,nr_tti_tx,&u,&v); // calculating u and v value
  alpha = nr_cyclic_shift_hopping(ue->pucch_config_common_nr->hoppingId,m0,mcs,lnormal,lprime,nr_tti_tx);
760
761

  for (int n=0; n<12; n++) {
762
    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)
763
                                         - (((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
764
    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)
765
                                         + (((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
766
    // PUCCH sequence = DM-RS sequence multiplied by d(0)
767
    y_n_re[n]               = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_re)>>15)
768
                                         - (((int32_t)(r_u_v_alpha_delta_im[n])*d_im)>>15))); // Re part of y(n)
769
    y_n_im[n]               = (int16_t)(((((int32_t)(r_u_v_alpha_delta_re[n])*d_im)>>15)
770
                                         + (((int32_t)(r_u_v_alpha_delta_im[n])*d_re)>>15))); // Im part of y(n)
771
772
773
    // DM-RS sequence
    r_u_v_alpha_delta_re[n] = (int16_t)(((int32_t)amp*r_u_v_alpha_delta_re[n])>>15);
    r_u_v_alpha_delta_im[n] = (int16_t)(((int32_t)amp*r_u_v_alpha_delta_im[n])>>15);
774
775
776
777
#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
778
  }
779

780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
  /*
   * 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_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)
   *
   * We are not implementing intra-slot hopping at the moment (so mprime=0)FIXME!
   */
#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
  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];
  // 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 FIXME!
  uint8_t w_index = timeDomainOCC; // to be filled with the value of timeDomainOCC, higher layers parameters FIXME !!!
  // 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;
809

810
  if (intraSlotFrequencyHopping == 0) { // intra-slot hopping disabled
811
812
813
814
#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\n",
           intraSlotFrequencyHopping);
#endif
815
816
817
818
    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)
819
820
821

    for (int m=0; m < N_SF_mprime_PUCCH_1; m++) {
      for (int n=0; n<12 ; n++) {
822
        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)
823
            - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15));
824
        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)
825
826
827
828
829
830
831
832
            + (((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\t z_pucch[%d] \t= ((%d \t* %d \t-%d \t* %d),   (%d \t* %d \t+%d \t*%d))    = (%d,%d)\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
833
834
      }
    }
835
836
837

    for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
      for (int n=0; n<12 ; n++) {
838
        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_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15)
839
            - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15));
840
        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_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15)
841
842
843
844
845
            + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15));
#ifdef DEBUG_NR_PUCCH_TX
        printf("\t\t z_dm-rs[%d] = ((),()) =(%d,%d)\n",
               (mprime*12*N_SF_mprime0_PUCCH_DMRS_1)+(m*12)+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
846
847
848
      }
    }
  }
849

850
  if (intraSlotFrequencyHopping == 1) { // intra-slot hopping enabled
851
852
853
854
#ifdef DEBUG_NR_PUCCH_TX
    printf("\t [nr_generate_pucch1] block-wise spread with the orthogonal sequence wi(m) if intraSlotFrequencyHopping = %d\n",
           intraSlotFrequencyHopping);
#endif
855
856
857
858
    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)
859
860
861
862

    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++) {
863
          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)
864
              - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_im[n])>>15));
865
          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)
866
              + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*y_n_re[n])>>15));
867
868
        }
      }
869
870
871

      for (int m=0; m < N_SF_mprime_PUCCH_DMRS_1; m++) {
        for (int n=0; n<12 ; n++) {
872
          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_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15)
873
              - (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15));
874
          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_1][w_index][m])*r_u_v_alpha_delta_im[n])>>15)
875
              + (((int32_t)(table_6_3_2_4_1_2_Wi_Im[N_SF_mprime_PUCCH_1][w_index][m])*r_u_v_alpha_delta_re[n])>>15));
876
877
        }
      }
878

879
880
881
882
      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)
    }
  }
883
884
885
886

  /*
   * Implementing TS 38.211 Subclause 6.3.2.4.2 Mapping to physical resources
   */
887
888
889
  int32_t *txptr;
  uint32_t re_offset;
  int i=0;
890

891
892
893
894
  for (int l=0; l<nrofSymbols; l++) {
    if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new PRB, FIXME!!!
      startingPRB = startingPRB + startingPRB_intraSlotHopping;
    }
895

896
897
898
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }
899

900
901
902
    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)));
    }
903

904
905
906
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*startingPRB) + frame_parms->first_carrier_offset;
    }
907

908
909
910
    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
      re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6;
    }
911

912
913
914
    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;
    }
915

916
    txptr = &txdataF[0][re_offset];
917
918

    for (int n=0; n<12; n++) {
919
920
921
922
      if ((n==6) && (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);
      }
923

924
925
926
      if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1
        ((int16_t *)&txdataF[0][re_offset])[0] = z_re[i+n];
        ((int16_t *)&txdataF[0][re_offset])[1] = z_im[i+n];
927
928
929
930
931
#ifdef DEBUG_NR_PUCCH_TX
        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(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n",
               amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset,
               l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
#endif
932
      }
933

934
935
936
      if (l%2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1
        ((int16_t *)&txdataF[0][re_offset])[0] = z_dmrs_re[i+n];
        ((int16_t *)&txdataF[0][re_offset])[1] = z_dmrs_im[i+n];
937
938
939
940
941
#ifdef DEBUG_NR_PUCCH_TX
        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(%d)=(x_n(l=%d,n=%d)=(%d,%d))\n",
               amp,frame_parms->ofdm_symbol_size,frame_parms->N_RB_DL,frame_parms->first_carrier_offset,i+n,re_offset,
               l,n,((int16_t *)&txdataF[0][re_offset])[0],((int16_t *)&txdataF[0][re_offset])[1]);
#endif
942
      }
943

944
945
      re_offset++;
    }
946

947
948
949
    if (l%2 == 1) i+=12;
  }
}
950
#endif //0
951
952
953

inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint32_t B,uint8_t *btilde) __attribute__((always_inline));
inline void nr_pucch2_3_4_scrambling(uint16_t M_bit,uint16_t rnti,uint16_t n_id,uint32_t B,uint8_t *btilde) {
954
955
956
957
958
959
960
  uint32_t x1, x2, s=0;
  int i;
  uint8_t c;
  // c_init=nRNTI*2^15+n_id according to TS 38.211 Subclause 6.3.2.6.1
  //x2 = (rnti) + ((uint32_t)(1+nr_tti_tx)<<16)*(1+(fp->Nid_cell<<1));
  x2 = ((rnti)<<15)+n_id;
  s = lte_gold_generic(&x1, &x2, 1);
961
#ifdef DEBUG_NR_PUCCH_TX
962
  printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%lx\n",s);
963
#endif
964
965
966
967

  for (i=0; i<M_bit; i++) {
    c = (uint8_t)((s>>i)&1);
    btilde[i] = (((B>>i)&1) ^ c);
968
#ifdef DEBUG_NR_PUCCH_TX
969
    //printf("\t\t\t btilde[%d]=%lx from scrambled bit %d\n",i,btilde[i],((B>>i)&1));
970
#endif
971
972
  }

973
#ifdef DEBUG_NR_PUCCH_TX
974
  printf("\t\t [nr_pucch2_3_4_scrambling] scrambling M_bit=%d bits\n", M_bit);
975
#endif
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
}
void nr_uci_encoding(uint64_t payload,
                     uint8_t nr_bit,
                     pucch_format_nr_t fmt,
                     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
995
  //uint8_t L;
996
  // E is the rate matching output sequence length as given in TS 38.212 subclause 6.3.1.4.1
997
  uint16_t E=0,E_init;
998

999
  if (fmt == pucch_format2_nr) E = 16*nrofSymbols*nrofPRB;
1000
1001

  if (fmt == pucch_format3_nr) {
1002
    E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12;
1003

1004
1005
    if (nrofSymbols == 4) {
      E = (intraSlotFrequencyHopping == 0)?(E_init*(nrofSymbols-1)*nrofPRB):((E_init*(nrofSymbols-1)*nrofPRB));
1006
1007
1008
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 3 nrofSymbols =4 and E_init=%d,E=%d\n",E_init,E);
#endif
1009
    }
1010

1011
1012
    if (nrofSymbols > 4)  {
      E = E_init*(nrofSymbols-2)*nrofPRB;
1013
1014
1015
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 3 nrofSymbols >4 and E_init=%d,E = %d\n",E_init,E);
#endif
1016
    }
1017

1018
1019
    if (nrofSymbols > 9)  {
      E = (add_dmrs == 0)?(E_init*(nrofSymbols-2)*nrofPRB):((E_init*(nrofSymbols-4)*nrofPRB));
1020
1021
1022
#ifdef DEBUG_NR_PUCCH_TX
      printf("format 3 nrofSymbols >9 and E_init=%d,E = %d\n",E_init,E);
#endif
1023
1024
    }
  }
1025
1026

  if (fmt == pucch_format4_nr) {
1027
    E_init = (is_pi_over_2_bpsk_enabled == 0) ? 24:12;