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

22
23
24
25
26
27
28
29
30
31
32
/*! \file PHY/LTE_TRANSPORT/pucch.c
* \brief Top-level routines for generating and decoding the PUCCH physical channel V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
#include "PHY/defs.h"
knopp's avatar
knopp committed
33
#include "PHY/extern.h" 
34
35
#include "LAYER2/MAC/extern.h"

36
37
38
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

39
40
#include "T.h"

gauthier's avatar
gauthier committed
41
//uint8_t ncs_cell[20][7];
42
43
//#define DEBUG_PUCCH_TX
//#define DEBUG_PUCCH_RX
44

gauthier's avatar
gauthier committed
45
int16_t cfo_pucch_np[24*7] = {20787,-25330,27244,-18205,31356,-9512,32767,0,31356,9511,27244,18204,20787,25329,
46
47
48
49
50
51
52
                              27244,-18205,30272,-12540,32137,-6393,32767,0,32137,6392,30272,12539,27244,18204,
                              31356,-9512,32137,-6393,32609,-3212,32767,0,32609,3211,32137,6392,31356,9511,
                              32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,
                              31356,9511,32137,6392,32609,3211,32767,0,32609,-3212,32137,-6393,31356,-9512,
                              27244,18204,30272,12539,32137,6392,32767,0,32137,-6393,30272,-12540,27244,-18205,
                              20787,25329,27244,18204,31356,9511,32767,0,31356,-9512,27244,-18205,20787,-25330
                             };
53

gauthier's avatar
gauthier committed
54
int16_t cfo_pucch_ep[24*6] = {24278,-22005,29621,-14010,32412,-4808,32412,4807,29621,14009,24278,22004,
55
56
57
58
59
60
61
                              28897,-15447,31356,-9512,32609,-3212,32609,3211,31356,9511,28897,15446,
                              31785,-7962,32412,-4808,32727,-1608,32727,1607,32412,4807,31785,7961,
                              32767,0,32767,0,32767,0,32767,0,32767,0,32767,0,
                              31785,7961,32412,4807,32727,1607,32727,-1608,32412,-4808,31785,-7962,
                              28897,15446,31356,9511,32609,3211,32609,-3212,31356,-9512,28897,-15447,
                              24278,22004,29621,14009,32412,4807,32412,-4808,29621,-14010,24278,-22005
                             };
62
63


64
65
void init_ncs_cell(LTE_DL_FRAME_PARMS *frame_parms,uint8_t ncs_cell[20][7])
{
66

gauthier's avatar
gauthier committed
67
68
  uint8_t ns,l,reset=1,i,N_UL_symb;
  uint32_t x1,x2,j=0,s=0;
69

70
71
72
  N_UL_symb = (frame_parms->Ncp==0) ? 7 : 6;
  x2 = frame_parms->Nid_cell;

73
  for (ns=0; ns<20; ns++) {
74

75
    for (l=0; l<N_UL_symb; l++) {
76
77
      ncs_cell[ns][l]=0;

78
79
80
81
82
83
84
85
86
87
88
      for (i=0; i<8; i++) {
        if ((j%32) == 0) {
          s = lte_gold_generic(&x1,&x2,reset);
          //    printf("s %x\n",s);
          reset=0;
        }

        if (((s>>(j%32))&1)==1)
          ncs_cell[ns][l] += (1<<i);

        j++;
89
      }
90

91
#ifdef DEBUG_PUCCH_TX
knopp's avatar
knopp committed
92
      printf("[PHY] PUCCH ncs_cell init (j %d): Ns %d, l %d => ncs_cell %d\n",j,ns,l,ncs_cell[ns][l]);
93
94
95
96
97
98
#endif
    }

  }
}

gauthier's avatar
gauthier committed
99
100
int16_t alpha_re[12] = {32767, 28377, 16383,     0,-16384,  -28378,-32768,-28378,-16384,    -1, 16383, 28377};
int16_t alpha_im[12] = {0,     16383, 28377, 32767, 28377,   16383,     0,-16384,-28378,-32768,-28378,-16384};
101

gauthier's avatar
gauthier committed
102
int16_t W4[3][4] = {{32767, 32767, 32767, 32767},
103
104
105
  {32767,-32768, 32767,-32768},
  {32767,-32768,-32768, 32767}
};
gauthier's avatar
gauthier committed
106
int16_t W3_re[3][6] = {{32767, 32767, 32767},
107
108
109
  {32767,-16384,-16384},
  {32767,-16384,-16384}
};
110

gauthier's avatar
gauthier committed
111
int16_t W3_im[3][6] = {{0    ,0     ,0     },
112
113
114
  {0    , 28377,-28378},
  {0    ,-28378, 28377}
};
115
116
117

char pucch_format_string[6][20] = {"format 1\0","format 1a\0","format 1b\0","format 2\0","format 2a\0","format 2b\0"};

knopp's avatar
knopp committed
118
119
120
121
122
123
124
125
126
127
void generate_pucch1x(int32_t **txdataF,
		      LTE_DL_FRAME_PARMS *frame_parms,
		      uint8_t ncs_cell[20][7],
		      PUCCH_FMT_t fmt,
		      PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
		      uint16_t n1_pucch,
		      uint8_t shortened_format,
		      uint8_t *payload,
		      int16_t amp,
		      uint8_t subframe)
128
129
{

gauthier's avatar
gauthier committed
130
131
132
133
134
135
136
137
138
139
140
  uint32_t u,v,n;
  uint32_t z[12*14],*zptr;
  int16_t d0;
  uint8_t ns,N_UL_symb,nsymb,n_oc,n_oc0,n_oc1;
  uint8_t c = (frame_parms->Ncp==0) ? 3 : 2;
  uint16_t nprime,nprime0,nprime1;
  uint16_t i,j,re_offset,thres,h;
  uint8_t Nprime_div_deltaPUCCH_Shift,Nprime,d;
  uint8_t m,l,refs;
  uint8_t n_cs,S,alpha_ind,rem;
  int16_t tmp_re,tmp_im,ref_re,ref_im,W_re=0,W_im=0;
141
  int32_t *txptr;
gauthier's avatar
gauthier committed
142
  uint32_t symbol_offset;
143

gauthier's avatar
gauthier committed
144
145
  uint8_t deltaPUCCH_Shift          = frame_parms->pucch_config_common.deltaPUCCH_Shift;
  uint8_t NRB2                      = frame_parms->pucch_config_common.nRB_CQI;
knopp's avatar
knopp committed
146
147
  uint8_t Ncs1                      = frame_parms->pucch_config_common.nCS_AN;
  uint8_t Ncs1_div_deltaPUCCH_Shift = Ncs1/deltaPUCCH_Shift;
148

fnabet's avatar
fnabet committed
149
150
151
  LOG_D(PHY,"generate_pucch Start [deltaPUCCH_Shift %d, NRB2 %d, Ncs1_div_deltaPUCCH_Shift %d, n1_pucch %d]\n", deltaPUCCH_Shift, NRB2, Ncs1_div_deltaPUCCH_Shift,n1_pucch);


gauthier's avatar
gauthier committed
152
153
154
155
  uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
  uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
  uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
  uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
156

157
  if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) {
knopp's avatar
knopp committed
158
    printf("[PHY] generate_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift);
159
160
161
162
    return;
  }

  if (Ncs1_div_deltaPUCCH_Shift > 7) {
knopp's avatar
knopp committed
163
    printf("[PHY] generate_pucch: Illegal Ncs1_div_deltaPUCCH_Shift %d (should be 0...7)\n",Ncs1_div_deltaPUCCH_Shift);
164
165
166
167
168
169
170
171
172
    return;
  }

  zptr = z;
  thres = (c*Ncs1_div_deltaPUCCH_Shift);
  Nprime_div_deltaPUCCH_Shift = (n1_pucch < thres) ? Ncs1_div_deltaPUCCH_Shift : (12/deltaPUCCH_Shift);
  Nprime = Nprime_div_deltaPUCCH_Shift * deltaPUCCH_Shift;

#ifdef DEBUG_PUCCH_TX
knopp's avatar
knopp committed
173
  printf("[PHY] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch);
174
175
#endif

fnabet's avatar
fnabet committed
176
177
178
179
180
  LOG_D(PHY,"[PHY] PUCCH: n1_pucch %d, thres %d Ncs1_div_deltaPUCCH_Shift %d (12/deltaPUCCH_Shift) %d Nprime_div_deltaPUCCH_Shift %d \n",
		              n1_pucch, thres, Ncs1_div_deltaPUCCH_Shift, (int)(12/deltaPUCCH_Shift), Nprime_div_deltaPUCCH_Shift);
  LOG_D(PHY,"[PHY] PUCCH: deltaPUCCH_Shift %d, Nprime %d\n",deltaPUCCH_Shift,Nprime);


181
182
183
184
185
  N_UL_symb = (frame_parms->Ncp==0) ? 7 : 6;

  if (n1_pucch < thres)
    nprime0=n1_pucch;
  else
186
187
    nprime0 = (n1_pucch - thres)%(12*c/deltaPUCCH_Shift);

188
189
190
191
192
  if (n1_pucch >= thres)
    nprime1= ((c*(nprime0+1))%((12*c/deltaPUCCH_Shift)+1))-1;
  else {
    d = (frame_parms->Ncp==0) ? 2 : 0;
    h= (nprime0+d)%(c*Nprime_div_deltaPUCCH_Shift);
193
194
195
#ifdef DEBUG_PUCCH_TX
    printf("[PHY] PUCCH: h %d, d %d\n",h,d);
#endif
196
    nprime1 = (h/c) + (h%c)*Nprime_div_deltaPUCCH_Shift;
197
198
199
  }

#ifdef DEBUG_PUCCH_TX
knopp's avatar
knopp committed
200
  printf("[PHY] PUCCH: nprime0 %d nprime1 %d, %s, payload (%d,%d)\n",nprime0,nprime1,pucch_format_string[fmt],payload[0],payload[1]);
201
202
203
#endif

  n_oc0 = nprime0/Nprime_div_deltaPUCCH_Shift;
204

205
206
207
208
  if (frame_parms->Ncp==1)
    n_oc0<<=1;

  n_oc1 = nprime1/Nprime_div_deltaPUCCH_Shift;
209

210
211
212
213
  if (frame_parms->Ncp==1)  // extended CP
    n_oc1<<=1;

#ifdef DEBUG_PUCCH_TX
214
  printf("[PHY] PUCCH: noc0 %d noc1 %d\n",n_oc0,n_oc1);
215
216
217
218
219
220
#endif

  nprime=nprime0;
  n_oc  =n_oc0;

  // loop over 2 slots
221
  for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) {
222
223
224
225
226
227
228

    if ((nprime&1) == 0)
      S=0;  // 1
    else
      S=1;  // j

    //loop over symbols in slot
229
    for (l=0; l<N_UL_symb; l++) {
230
231
      // Compute n_cs (36.211 p. 18)
      n_cs = ncs_cell[ns][l];
232

233
      if (frame_parms->Ncp==0) { // normal CP
234
235
236
        n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc%deltaPUCCH_Shift))%Nprime)%12;
      } else {
        n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc>>1))%Nprime)%12;
237
238
239
240
      }


      refs=0;
241

242
243
244
      // Comput W_noc(m) (36.211 p. 19)
      if ((ns==(1+(subframe<<1))) && (shortened_format==1)) {  // second slot and shortened format

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
        if (l<2) {                                         // data
          W_re=W3_re[n_oc][l];
          W_im=W3_im[n_oc][l];
        } else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==0)) { // reference and normal CP
          W_re=W3_re[n_oc][l-2];
          W_im=W3_im[n_oc][l-2];
          refs=1;
        } else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==1)) { // reference and extended CP
          W_re=W4[n_oc][l-2];
          W_im=0;
          refs=1;
        } else if ((l>=N_UL_symb-2)) {                      // data
          W_re=W3_re[n_oc][l-N_UL_symb+4];
          W_im=W3_im[n_oc][l-N_UL_symb+4];
        }
      } else {
        if (l<2) {                                         // data
          W_re=W4[n_oc][l];
          W_im=0;
        } else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==0)) { // reference and normal CP
          W_re=W3_re[n_oc][l-2];
          W_im=W3_im[n_oc][l-2];
          refs=1;
        } else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==1)) { // reference and extended CP
          W_re=W4[n_oc][l-2];
          W_im=0;
          refs=1;
        } else if ((l>=N_UL_symb-2)) {                     // data
          W_re=W4[n_oc][l-N_UL_symb+4];
          W_im=0;
        }
276
277
      }

278
      // multiply W by S(ns) (36.211 p.17). only for data, reference symbols do not have this factor
279
      if ((S==1)&&(refs==0)) {
280
281
282
        tmp_re = W_re;
        W_re = -W_im;
        W_im = tmp_re;
283
284
285
      }

#ifdef DEBUG_PUCCH_TX
knopp's avatar
knopp committed
286
      printf("[PHY] PUCCH: ncs[%d][%d]=%d, W_re %d, W_im %d, S %d, refs %d\n",ns,l,n_cs,W_re,W_im,S,refs);
287
288
#endif
      alpha_ind=0;
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
      // compute output sequence

      for (n=0; n<12; n++) {

        // this is r_uv^alpha(n)
        tmp_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
        tmp_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);

        // this is S(ns)*w_noc(m)*r_uv^alpha(n)
        ref_re = (tmp_re*W_re - tmp_im*W_im)>>15;
        ref_im = (tmp_re*W_im + tmp_im*W_re)>>15;

        if ((l<2)||(l>=(N_UL_symb-2))) { //these are PUCCH data symbols
          switch (fmt) {
          case pucch_format1:   //OOK 1-bit

            ((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re)>>15;
            ((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im)>>15;

            break;

          case pucch_format1a:  //BPSK 1-bit
            d0 = (payload[0]&1)==0 ? amp : -amp;
            ((int16_t *)&zptr[n])[0] = ((int32_t)d0*ref_re)>>15;
            ((int16_t *)&zptr[n])[1] = ((int32_t)d0*ref_im)>>15;
            //      printf("d0 %d\n",d0);
            break;

          case pucch_format1b:  //QPSK 2-bits (Table 5.4.1-1 from 36.211, pg. 18)
            if (((payload[0]&1)==0) && ((payload[1]&1)==0))  {// 1
              ((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re)>>15;
              ((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im)>>15;
            } else if (((payload[0]&1)==0) && ((payload[1]&1)==1))  { // -j
              ((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_im)>>15;
              ((int16_t *)&zptr[n])[1] = (-(int32_t)amp*ref_re)>>15;
            } else if (((payload[0]&1)==1) && ((payload[1]&1)==0))  { // j
              ((int16_t *)&zptr[n])[0] = (-(int32_t)amp*ref_im)>>15;
              ((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_re)>>15;
            } else  { // -1
              ((int16_t *)&zptr[n])[0] = (-(int32_t)amp*ref_re)>>15;
              ((int16_t *)&zptr[n])[1] = (-(int32_t)amp*ref_im)>>15;
            }

            break;

          case pucch_format2:
          case pucch_format2a:
          case pucch_format2b:
knopp's avatar
knopp committed
337
            AssertFatal(1==0,"should not go here\n");
338
339
340
341
342
343
344
345
346
            break;
          } // switch fmt
        } else { // These are PUCCH reference symbols

          ((int16_t *)&zptr[n])[0] = ((int32_t)amp*ref_re)>>15;
          ((int16_t *)&zptr[n])[1] = ((int32_t)amp*ref_im)>>15;
          //    printf("ref\n");
        }

347
#ifdef DEBUG_PUCCH_TX
knopp's avatar
knopp committed
348
        printf("[PHY] PUCCH subframe %d z(%d,%d) => %d,%d, alpha(%d) => %d,%d\n",subframe,l,n,((int16_t *)&zptr[n])[0],((int16_t *)&zptr[n])[1],
349
            alpha_ind,alpha_re[alpha_ind],alpha_im[alpha_ind]);
350
#endif
351
        alpha_ind = (alpha_ind + n_cs)%12;
352
      } // n
353

354
355
356
      zptr+=12;
    } // l

357
358
    nprime=nprime1;
    n_oc  =n_oc1;
359
360
361
362
363
364
365
  } // ns

  rem = ((((12*Ncs1_div_deltaPUCCH_Shift)>>3)&7)>0) ? 1 : 0;

  m = (n1_pucch < thres) ? NRB2 : (((n1_pucch-thres)/(12*c/deltaPUCCH_Shift))+NRB2+((deltaPUCCH_Shift*Ncs1_div_deltaPUCCH_Shift)>>3)+rem);

#ifdef DEBUG_PUCCH_TX
knopp's avatar
knopp committed
366
  printf("[PHY] PUCCH: m %d\n",m);
367
368
369
370
#endif
  nsymb = N_UL_symb<<1;

  //for (j=0,l=0;l<(nsymb-1);l++) {
371
  for (j=0,l=0; l<(nsymb); l++) {
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    if ((l<(nsymb>>1)) && ((m&1) == 0))
      re_offset = (m*6) + frame_parms->first_carrier_offset;
    else if ((l<(nsymb>>1)) && ((m&1) == 1))
      re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
    else if ((m&1) == 0)
      re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
    else
      re_offset = ((m-1)*6) + frame_parms->first_carrier_offset;

    if (re_offset > frame_parms->ofdm_symbol_size)
      re_offset -= (frame_parms->ofdm_symbol_size);

    symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*(l+(subframe*nsymb));
    txptr = &txdataF[0][symbol_offset];

387
    for (i=0; i<12; i++,j++) {
388
      txptr[re_offset++] = z[j];
389

390
      if (re_offset==frame_parms->ofdm_symbol_size)
391
392
        re_offset = 0;

393
#ifdef DEBUG_PUCCH_TX
knopp's avatar
knopp committed
394
      printf("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
395
396
397
398
399
400
#endif
    }
  }

}

401
void generate_pucch_emul(PHY_VARS_UE *ue,
402
			 UE_rxtx_proc_t *proc,
403
404
405
                         PUCCH_FMT_t format,
                         uint8_t ncs1,
                         uint8_t *pucch_payload,
406
407
                         uint8_t sr)

408
{
409

410
  int subframe = proc->subframe_tx;
411

412
413
  UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_flag    = format;
  UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_Ncs1    = ncs1;
414

415

416
417
418
  UE_transport_info[ue->Mod_id][ue->CC_id].cntl.sr            = sr;
  // the value of ue->pucch_sel[subframe] is set by get_n1_pucch
  UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_sel      = ue->pucch_sel[subframe];
419

420
  // LOG_I(PHY,"subframe %d emu tx pucch_sel is %d sr is %d \n", subframe, UE_transport_info[ue->Mod_id].cntl.pucch_sel, sr);
421

422
  if (format == pucch_format1a) {
423

424
425
    ue->pucch_payload[0] = pucch_payload[0];
    UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_payload = pucch_payload[0];
426
  } else if (format == pucch_format1b) {
427
428
    ue->pucch_payload[0] = pucch_payload[0] + (pucch_payload[1]<<1);
    UE_transport_info[ue->Mod_id][ue->CC_id].cntl.pucch_payload = pucch_payload[0] + (pucch_payload[1]<<1);
429
  } else if (format == pucch_format1) {
knopp's avatar
knopp committed
430
    //    LOG_D(PHY,"[UE %d] Frame %d subframe %d Generating PUCCH for SR %d\n",ue->Mod_id,proc->frame_tx,subframe,sr);
431
  }
432

433
  ue->sr[subframe] = sr;
434
435
436

}

knopp's avatar
knopp committed
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) __attribute__((always_inline));
inline void pucch2x_scrambling(LTE_DL_FRAME_PARMS *fp,int subframe,uint16_t rnti,uint32_t B,uint8_t *btilde) {

  uint32_t x1, x2, s=0;
  int i;
  uint8_t c;

  x2 = (rnti<<14) + ((1+subframe)<<16)*(1+(fp->Nid_cell<<1)); //this is c_init in 36.211 Sec 6.3.1
  s = lte_gold_generic(&x1, &x2, 1);
  for (i=0;i<19;i++) {
    c = (uint8_t)((s>>i)&1);
    btilde[i] = (((B>>i)&1) ^ c);
  }
}

inline void pucch2x_modulation(uint8_t *btilde,int16_t *d,int16_t amp) __attribute__((always_inline));
inline void pucch2x_modulation(uint8_t *btilde,int16_t *d,int16_t amp) {

  int i;

  for (i=0;i<20;i++) 
    d[i] = btilde[i] == 1 ? amp : -amp;

}

knopp's avatar
knopp committed
463
464


knopp's avatar
knopp committed
465
466
467
468
uint32_t pucch_code[13] = {0xFFFFF,0x5A933,0x10E5A,0x6339C,0x73CE0,
			   0xFFC00,0xD8E64,0x4F6B0,0x218EC,0x1B746,
			   0x0FFFF,0x33FFF,0x3FFFC};

knopp's avatar
knopp committed
469

knopp's avatar
knopp committed
470
471
472
473
474
475
476
void generate_pucch2x(int32_t **txdataF,
		      LTE_DL_FRAME_PARMS *fp,
		      uint8_t ncs_cell[20][7],
		      PUCCH_FMT_t fmt,
		      PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
		      uint16_t n2_pucch,
		      uint8_t shortened_format,
knopp's avatar
knopp committed
477
		      uint16_t *payload,
knopp's avatar
knopp committed
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
		      int A,
		      int B2,
		      int16_t amp,
		      uint8_t subframe,
		      uint16_t rnti) {

  int i,j;
  uint32_t B=0;
  uint8_t btilde[20];
  int16_t d[22];
  uint8_t deltaPUCCH_Shift          = fp->pucch_config_common.deltaPUCCH_Shift;
  uint8_t NRB2                      = fp->pucch_config_common.nRB_CQI;
  uint8_t Ncs1                      = fp->pucch_config_common.nCS_AN;

  uint32_t u0 = (fp->Nid_cell + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
  uint32_t u1 = (fp->Nid_cell + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
  uint32_t v0=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
  uint32_t v1=fp->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
  uint32_t z[12*14],*zptr;
  uint32_t u,v,n;
  uint8_t ns,N_UL_symb,nsymb;
  uint32_t nprime,l,n_cs;
  int alpha_ind,data_ind;
  int16_t ref_re,ref_im;
  int m,re_offset,symbol_offset;
  int32_t *txptr;

  if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) {
    printf("[PHY] generate_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift);
    return;
  }

  if (Ncs1 > 7) {
    printf("[PHY] generate_pucch: Illegal Ncs1 %d (should be 0...7)\n",Ncs1);
    return;
  }


  // pucch2x_encoding
  for (i=0;i<A;i++)
    if ((*payload & (1<<i)) > 0)
      B=B^pucch_code[i];

  // scrambling
  pucch2x_scrambling(fp,subframe,rnti,B,btilde);
  // modulation
  pucch2x_modulation(btilde,d,amp);

  // add extra symbol for 2a/2b
  d[20]=0;
  d[21]=0;
  if (fmt==pucch_format2a)
    d[20] = (B2 == 0) ? amp : -amp;
  else if (fmt==pucch_format2b) {
    switch (B2) {
    case 0:
      d[20] = amp;
      break;
    case 1:
      d[21] = -amp;
      break;
    case 2:
      d[21] = amp;
      break;
    case 3:
      d[20] = -amp;
      break;
    default:
      AssertFatal(1==0,"Illegal modulation symbol %d for PUCCH %s\n",B2,pucch_format_string[fmt]);
      break;
    }
  }

  zptr = z;

#ifdef DEBUG_PUCCH_TX
  printf("[PHY] PUCCH2x: n2_pucch %d\n",n2_pucch);
#endif

  N_UL_symb = (fp->Ncp==0) ? 7 : 6;

  for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) {

    if ((ns&1) == 0)
      nprime = (n2_pucch < 12*NRB2) ? 
	n2_pucch % 12 :
	(n2_pucch+Ncs1 + 1)%12;
knopp's avatar
knopp committed
565
    else {
knopp's avatar
knopp committed
566
567
568
      nprime = (n2_pucch < 12*NRB2) ? 
        ((12*(nprime+1)) % 13)-1 :
	(10-n2_pucch)%12;
knopp's avatar
knopp committed
569
570
571
      if (shortened_format == 1)
	N_UL_symb--;
    }
knopp's avatar
knopp committed
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594

    //loop over symbols in slot
    for (l=0; l<N_UL_symb; l++) {
      // Compute n_cs (36.211 p. 18)
      n_cs = (ncs_cell[ns][l]+nprime)%12;

      alpha_ind = n_cs;
      data_ind = 0;

      for (n=0; n<12; n++) {

        // this is r_uv^alpha(n)
        ref_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
        ref_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);

        if ((l<2)||(l>=(N_UL_symb-2))) { //these are PUCCH data symbols
	  ((int16_t *)&zptr[n])[0] = ((int32_t)d[data_ind]*ref_re - (int32_t)d[data_ind+1]*ref_im)>>15;
	  ((int16_t *)&zptr[n])[1] = ((int32_t)d[data_ind]*ref_im + (int32_t)d[data_ind+1]*ref_re)>>15;
	}
	else {
	  ((int16_t *)&zptr[n])[0] = ref_re;
	  ((int16_t *)&zptr[n])[1] = ref_im;
	}
595

knopp's avatar
knopp committed
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
      } // n
      if ((l<2)||(l>=(N_UL_symb-2)))  //these are PUCCH data symbols so increment data index
	data_ind+=2;
    } // l
  } //ns

  m = n2_pucch/12;

#ifdef DEBUG_PUCCH_TX
  printf("[PHY] PUCCH: m %d\n",m);
#endif
  nsymb = N_UL_symb<<1;

  //for (j=0,l=0;l<(nsymb-1);l++) {
  for (j=0,l=0; l<(nsymb); l++) {
    if ((l<(nsymb>>1)) && ((m&1) == 0))
      re_offset = (m*6) + fp->first_carrier_offset;
    else if ((l<(nsymb>>1)) && ((m&1) == 1))
      re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12;
    else if ((m&1) == 0)
      re_offset = fp->first_carrier_offset + (fp->N_RB_DL - (m>>1) - 1)*12;
    else
      re_offset = ((m-1)*6) + fp->first_carrier_offset;

    if (re_offset > fp->ofdm_symbol_size)
      re_offset -= (fp->ofdm_symbol_size);

    symbol_offset = (unsigned int)fp->ofdm_symbol_size*(l+(subframe*nsymb));
    txptr = &txdataF[0][symbol_offset];

    for (i=0; i<12; i++,j++) {
      txptr[re_offset++] = z[j];

      if (re_offset==fp->ofdm_symbol_size)
        re_offset = 0;

#ifdef DEBUG_PUCCH_TX
      printf("[PHY] PUCCH subframe %d (%d,%d,%d,%d) => %d,%d\n",subframe,l,i,re_offset-1,m,((int16_t *)&z[j])[0],((int16_t *)&z[j])[1]);
#endif
    }
  }
637
638
}

knopp's avatar
knopp committed
639

knopp's avatar
knopp committed
640
641
642
643
//#define Amax 13
//void init_pucch2x_rx() {};


644
uint32_t rx_pucch(PHY_VARS_eNB *eNB,
645
646
647
648
649
650
		  PUCCH_FMT_t fmt,
		  uint8_t UE_id,
		  uint16_t n1_pucch,
		  uint16_t n2_pucch,
		  uint8_t shortened_format,
		  uint8_t *payload,
651
		  int     frame,
652
653
		  uint8_t subframe,
		  uint8_t pucch1_thres)
654
{
655
656


657
  static int first_call=1;
658
659
660
661
662
663
664
665
666
  LTE_eNB_COMMON *common_vars                = &eNB->common_vars;
  LTE_DL_FRAME_PARMS *frame_parms                    = &eNB->frame_parms;
  //  PUCCH_CONFIG_DEDICATED *pucch_config_dedicated = &eNB->pucch_config_dedicated[UE_id];
  int8_t sigma2_dB                                   = eNB->measurements[0].n0_subband_power_tot_dB[0]-10;
  uint32_t *Po_PUCCH                                  = &(eNB->UE_stats[UE_id].Po_PUCCH);
  int32_t *Po_PUCCH_dBm                              = &(eNB->UE_stats[UE_id].Po_PUCCH_dBm);
  uint32_t *Po_PUCCH1_below                           = &(eNB->UE_stats[UE_id].Po_PUCCH1_below);
  uint32_t *Po_PUCCH1_above                           = &(eNB->UE_stats[UE_id].Po_PUCCH1_above);
  int32_t *Po_PUCCH_update                           = &(eNB->UE_stats[UE_id].Po_PUCCH_update);
gauthier's avatar
gauthier committed
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
  uint32_t u,v,n,aa;
  uint32_t z[12*14];
  int16_t *zptr;
  int16_t rxcomp[NB_ANTENNAS_RX][2*12*14];
  uint8_t ns,N_UL_symb,nsymb,n_oc,n_oc0,n_oc1;
  uint8_t c = (frame_parms->Ncp==0) ? 3 : 2;
  uint16_t nprime,nprime0,nprime1;
  uint16_t i,j,re_offset,thres,h,off;
  uint8_t Nprime_div_deltaPUCCH_Shift,Nprime,d;
  uint8_t m,l,refs,phase,re,l2,phase_max=0;
  uint8_t n_cs,S,alpha_ind,rem;
  int16_t tmp_re,tmp_im,W_re=0,W_im=0;
  int16_t *rxptr;
  uint32_t symbol_offset;
  int16_t stat_ref_re,stat_ref_im,*cfo,chest_re,chest_im;
  int32_t stat_re=0,stat_im=0;
683
  uint32_t stat,stat_max=0;
gauthier's avatar
gauthier committed
684
685
686
687
688
689
690
691
692

  uint8_t deltaPUCCH_Shift          = frame_parms->pucch_config_common.deltaPUCCH_Shift;
  uint8_t NRB2                      = frame_parms->pucch_config_common.nRB_CQI;
  uint8_t Ncs1_div_deltaPUCCH_Shift = frame_parms->pucch_config_common.nCS_AN;

  uint32_t u0 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[subframe<<1]) % 30;
  uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30;
  uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1];
  uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)];
693
  int chL;
694

695
696
697
  if (first_call == 1) {
    for (i=0;i<10;i++) {
      for (j=0;j<NUMBER_OF_UE_MAX;j++) {
698
699
	eNB->pucch1_stats_cnt[j][i]=0;
	eNB->pucch1ab_stats_cnt[j][i]=0;
700
701
702
703
      }
    }
    first_call=0;
  }
704
  /*
knopp's avatar
knopp committed
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
  switch (frame_parms->N_RB_UL) {

  case 6:
    sigma2_dB -= 8;
    break;
  case 25:
    sigma2_dB -= 14;
    break;
  case 50:
    sigma2_dB -= 17;
    break;
  case 100:
    sigma2_dB -= 20;
    break;
  default:
    sigma2_dB -= 14;
  }
722
  */  
knopp's avatar
knopp committed
723

724
    
725
726
727
728
729
730
731
732
733
734
  if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) {
    LOG_E(PHY,"[eNB] rx_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift);
    return(-1);
  }

  if (Ncs1_div_deltaPUCCH_Shift > 7) {
    LOG_E(PHY,"[eNB] rx_pucch: Illegal Ncs1_div_deltaPUCCH_Shift %d (should be 0...7)\n",Ncs1_div_deltaPUCCH_Shift);
    return(-1);
  }

gauthier's avatar
gauthier committed
735
  zptr = (int16_t *)z;
736
737
738
739
740
  thres = (c*Ncs1_div_deltaPUCCH_Shift);
  Nprime_div_deltaPUCCH_Shift = (n1_pucch < thres) ? Ncs1_div_deltaPUCCH_Shift : (12/deltaPUCCH_Shift);
  Nprime = Nprime_div_deltaPUCCH_Shift * deltaPUCCH_Shift;

#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
741
  printf("[eNB] PUCCH: cNcs1/deltaPUCCH_Shift %d, Nprime %d, n1_pucch %d\n",thres,Nprime,n1_pucch);
742
743
#endif

744
  N_UL_symb = (frame_parms->Ncp==NORMAL) ? 7 : 6;
745
746
747
748

  if (n1_pucch < thres)
    nprime0=n1_pucch;
  else
749
750
    nprime0 = (n1_pucch - thres)%(12*c/deltaPUCCH_Shift);

751
752
753
754
755
  if (n1_pucch >= thres)
    nprime1= ((c*(nprime0+1))%((12*c/deltaPUCCH_Shift)+1))-1;
  else {
    d = (frame_parms->Ncp==0) ? 2 : 0;
    h= (nprime0+d)%(c*Nprime_div_deltaPUCCH_Shift);
756
    nprime1 = (h/c) + (h%c)*Nprime_div_deltaPUCCH_Shift;
757
758
759
  }

#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
760
  printf("PUCCH: nprime0 %d nprime1 %d\n",nprime0,nprime1);
761
762
763
#endif

  n_oc0 = nprime0/Nprime_div_deltaPUCCH_Shift;
764

765
766
767
768
  if (frame_parms->Ncp==1)
    n_oc0<<=1;

  n_oc1 = nprime1/Nprime_div_deltaPUCCH_Shift;
769

770
771
772
773
  if (frame_parms->Ncp==1)  // extended CP
    n_oc1<<=1;

#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
774
  printf("[eNB] PUCCH: noc0 %d noc11 %d\n",n_oc0,n_oc1);
775
776
777
778
779
780
#endif

  nprime=nprime0;
  n_oc  =n_oc0;

  // loop over 2 slots
781
  for (ns=(subframe<<1),u=u0,v=v0; ns<(2+(subframe<<1)); ns++,u=u1,v=v1) {
782
783
784
785
786

    if ((nprime&1) == 0)
      S=0;  // 1
    else
      S=1;  // j
787
788
789
790
791
792
    /*
    if (fmt==pucch_format1)
      LOG_I(PHY,"[eNB] subframe %d => PUCCH1: u%d %d, v%d %d : ", subframe,ns&1,u,ns&1,v);
    else
      LOG_I(PHY,"[eNB] subframe %d => PUCCH1a/b: u%d %d, v%d %d : ", subframe,ns&1,u,ns&1,v);
    */
793
794

    //loop over symbols in slot
795
    for (l=0; l<N_UL_symb; l++) {
796
      // Compute n_cs (36.211 p. 18)
797
      n_cs = eNB->ncs_cell[ns][l];
798

799
      if (frame_parms->Ncp==0) { // normal CP
800
801
802
        n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc%deltaPUCCH_Shift))%Nprime)%12;
      } else {
        n_cs = ((uint16_t)n_cs + (nprime*deltaPUCCH_Shift + (n_oc>>1))%Nprime)%12;
803
804
805
      }


806

807
      refs=0;
808

809
810
811
      // Comput W_noc(m) (36.211 p. 19)
      if ((ns==(1+(subframe<<1))) && (shortened_format==1)) {  // second slot and shortened format

812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
        if (l<2) {                                         // data
          W_re=W3_re[n_oc][l];
          W_im=W3_im[n_oc][l];
        } else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==0)) { // reference and normal CP
          W_re=W3_re[n_oc][l-2];
          W_im=W3_im[n_oc][l-2];
          refs=1;
        } else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==1)) { // reference and extended CP
          W_re=W4[n_oc][l-2];
          W_im=0;
          refs=1;
        } else if ((l>=N_UL_symb-2)) {                      // data
          W_re=W3_re[n_oc][l-N_UL_symb+4];
          W_im=W3_im[n_oc][l-N_UL_symb+4];
        }
      } else {
        if (l<2) {                                         // data
          W_re=W4[n_oc][l];
          W_im=0;
831
        } else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==NORMAL)) { // reference and normal CP
832
833
834
          W_re=W3_re[n_oc][l-2];
          W_im=W3_im[n_oc][l-2];
          refs=1;
835
        } else if ((l<N_UL_symb-2)&&(frame_parms->Ncp==EXTENDED)) { // reference and extended CP
836
837
838
839
840
841
842
          W_re=W4[n_oc][l-2];
          W_im=0;
          refs=1;
        } else if ((l>=N_UL_symb-2)) {                     // data
          W_re=W4[n_oc][l-N_UL_symb+4];
          W_im=0;
        }
843
844
      }

845
      // multiply W by S(ns) (36.211 p.17). only for data, reference symbols do not have this factor
846
      if ((S==1)&&(refs==0)) {
847
848
849
        tmp_re = W_re;
        W_re = -W_im;
        W_im = tmp_re;
850
851
852
      }

#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
853
      printf("[eNB] PUCCH: ncs[%d][%d]=%d, W_re %d, W_im %d, S %d, refs %d\n",ns,l,n_cs,W_re,W_im,S,refs);
854
855
#endif
      alpha_ind=0;
856
      // compute output sequence
857

858
      for (n=0; n<12; n++) {
859

860
861
862
        // this is r_uv^alpha(n)
        tmp_re = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][n<<1] - (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)])>>15);
        tmp_im = (int16_t)(((int32_t)alpha_re[alpha_ind] * ul_ref_sigs[u][v][0][1+(n<<1)] + (int32_t)alpha_im[alpha_ind] * ul_ref_sigs[u][v][0][n<<1])>>15);
863

864
865
866
        // this is S(ns)*w_noc(m)*r_uv^alpha(n)
        zptr[n<<1] = (tmp_re*W_re - tmp_im*W_im)>>15;
        zptr[1+(n<<1)] = -(tmp_re*W_im + tmp_im*W_re)>>15;
867
868

#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
869
        printf("[eNB] PUCCH subframe %d z(%d,%d) => %d,%d, alpha(%d) => %d,%d\n",subframe,l,n,zptr[n<<1],zptr[(n<<1)+1],
870
              alpha_ind,alpha_re[alpha_ind],alpha_im[alpha_ind]);
871
#endif
872

873
        alpha_ind = (alpha_ind + n_cs)%12;
874
      } // n
875

876
877
878
      zptr+=24;
    } // l

879
880
    nprime=nprime1;
    n_oc  =n_oc1;
881
882
883
884
885
886
887
  } // ns

  rem = ((((deltaPUCCH_Shift*Ncs1_div_deltaPUCCH_Shift)>>3)&7)>0) ? 1 : 0;

  m = (n1_pucch < thres) ? NRB2 : (((n1_pucch-thres)/(12*c/deltaPUCCH_Shift))+NRB2+((deltaPUCCH_Shift*Ncs1_div_deltaPUCCH_Shift)>>3)+rem);

#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
888
  printf("[eNB] PUCCH: m %d\n",m);
889
890
891
#endif
  nsymb = N_UL_symb<<1;

gauthier's avatar
gauthier committed
892
  zptr = (int16_t*)z;
893
894

  // Do detection
895
896
  for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {

897
    //for (j=0,l=0;l<(nsymb-1);l++) {
898
    for (j=0,l=0; l<nsymb; l++) {
899
      if ((l<(nsymb>>1)) && ((m&1) == 0))
900
        re_offset = (m*6) + frame_parms->first_carrier_offset;
901
      else if ((l<(nsymb>>1)) && ((m&1) == 1))
902
        re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
903
      else if ((m&1) == 0)
904
        re_offset = frame_parms->first_carrier_offset + (frame_parms->N_RB_DL - (m>>1) - 1)*12;
905
      else
906
907
        re_offset = ((m-1)*6) + frame_parms->first_carrier_offset;

908
      if (re_offset > frame_parms->ofdm_symbol_size)
909
910
        re_offset -= (frame_parms->ofdm_symbol_size);

911
      symbol_offset = (unsigned int)frame_parms->ofdm_symbol_size*l;
912
      rxptr = (int16_t *)&common_vars->rxdataF[0][aa][symbol_offset];
913
914

      for (i=0; i<12; i++,j+=2,re_offset++) {
915
916
        rxcomp[aa][j]   = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[j])>>15)   - ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[1+j])>>15);
        rxcomp[aa][1+j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[1+j])>>15) + ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[j])>>15);
917
918
919
920

        if (re_offset==frame_parms->ofdm_symbol_size)
          re_offset = 0;

921
#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
922
        printf("[eNB] PUCCH subframe %d (%d,%d,%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,i,re_offset,m,j,
923
              rxptr[re_offset<<1],rxptr[1+(re_offset<<1)],
924
925
              zptr[j],zptr[1+j],
              rxcomp[aa][j],rxcomp[aa][1+j]);
926
927
928
929
930
931
932
933
934
935
936
#endif
      } //re
    } // symbol
  }  // antenna


  // PUCCH Format 1
  // Do cfo correction and MRC across symbols

  if (fmt == pucch_format1) {
#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
937
    printf("Doing PUCCH detection for format 1\n");
938
939
940
#endif

    stat_max = 0;
941
942
943


    for (phase=0; phase<7; phase++) {
944
      stat=0;
945
946
947
948
949
950
951
952
953

      for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
        for (re=0; re<12; re++) {
          stat_re=0;
          stat_im=0;
          off=re<<1;
          cfo =  (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase] : &cfo_pucch_ep[12*phase];

          for (l=0; l<(nsymb>>1); l++) {
954
955
            stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15)     - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/nsymb;
            stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/nsymb;
956
            off+=2;
957
958

		    
959
#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
960
            printf("[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) , stat %d\n",subframe,phase,l,re,
961
962
                  rxcomp[aa][off],rxcomp[aa][1+off],
                  cfo[l<<1],cfo[1+(l<<1)],
963
                  stat_re,stat_im,stat);
964
965
966
967
#endif
          }

          for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) {
968
969
            stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15)     - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15))/nsymb;
            stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15))/nsymb;
970
            off+=2;
971

972
#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
973
            printf("[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d), stat %d\n",subframe,phase,l2,re,
974
975
                  rxcomp[aa][off],rxcomp[aa][1+off],
                  cfo[l2<<1],cfo[1+(l2<<1)],
976
                  stat_re,stat_im,stat);
977
978
#endif

979

980
          }
981
982
	  stat += ((stat_re*stat_re) + (stat_im*stat_im));

983
       } //re
984
985
      } // aa

986
 
987
      if (stat>stat_max) {
988
989
        stat_max = stat;
        phase_max = phase;
990
      }
991

992
993
    } //phase

994
995
    stat_max *= nsymb;  // normalize to energy per symbol
    stat_max /= (frame_parms->N_RB_UL*12); // 
996
#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
997
    printf("[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max);
998
#endif
999
1000

#ifdef DEBUG_PUCCH_RX
1001
    LOG_I(PHY,"[eNB] PUCCH fmt1:  stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max);
1002
#endif
1003

1004
1005
1006
    eNB->pucch1_stats[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = stat_max;
    eNB->pucch1_stats_thres[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres;
    eNB->pucch1_stats_cnt[UE_id][subframe] = (eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023;
1007

Cedric Roux's avatar
Cedric Roux committed
1008
    T(T_ENB_PHY_PUCCH_1_ENERGY, T_INT(eNB->Mod_id), T_INT(UE_id), T_INT(frame), T_INT(subframe),
1009
1010
      T_INT(stat_max), T_INT(sigma2_dB+pucch1_thres));

1011
    /*
1012
    if (eNB->pucch1_stats_cnt[UE_id][subframe] == 0) {
1013
      write_output("pucch_debug.m","pucch_energy",
1014
		   &eNB->pucch1_stats[UE_id][(subframe<<10)],
1015
1016
1017
1018
1019
1020
		   1024,1,2);
      AssertFatal(0,"Exiting for PUCCH 1 debug\n");

    }
    */

knopp's avatar
knopp committed
1021
1022
    // This is a moving average of the PUCCH1 statistics conditioned on being above or below the threshold
    if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres))  {
1023
      *payload = 1;
1024
      *Po_PUCCH1_above = ((*Po_PUCCH1_above<<9) + (stat_max<<9)+1024)>>10;
1025
      //LOG_I(PHY,"[eNB] PUCCH fmt1:  stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max);
knopp's avatar
knopp committed
1026
1027
    }
    else {
1028
      *payload = 0;
1029
      *Po_PUCCH1_below = ((*Po_PUCCH1_below<<9) + (stat_max<<9)+1024)>>10;
knopp's avatar
knopp committed
1030
    }
1031
    //printf("[eNB] PUCCH fmt1:  stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,eNB->measurements[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above));
knopp's avatar
knopp committed
1032
    *Po_PUCCH_update = 1;
1033
1034
1035
1036
    if (UE_id==0) {
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_ENERGY,dB_fixed(stat_max));
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_THRES,sigma2_dB+pucch1_thres);
    }
1037
  } else if ((fmt == pucch_format1a)||(fmt == pucch_format1b)) {
1038
1039
    stat_max = 0;
#ifdef DEBUG_PUCCH_RX
1040
    LOG_I(PHY,"Doing PUCCH detection for format 1a/1b\n");
1041
#endif
1042

1043
    for (phase=3;phase<4;phase++){ //phase=0; phase<7; phase++) {
1044
      stat=0;
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065

      for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
        for (re=0; re<12; re++) {
          stat_re=0;
          stat_im=0;
          stat_ref_re=0;
          stat_ref_im=0;
          off=re<<1;
          cfo =  (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase] : &cfo_pucch_ep[12*phase];


          for (l=0; l<(nsymb>>1); l++) {
            if ((l<2)||(l>(nsymb>>1) - 3)) {  //data symbols
              stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15)     - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
              stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
            } else { //reference symbols
              stat_ref_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15)     - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
              stat_ref_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
            }

            off+=2;
1066
#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
1067
            printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re,
1068
1069
1070
1071
1072
1073
                  rxcomp[aa][off],rxcomp[aa][1+off],
                  cfo[l<<1],cfo[1+(l<<1)],
                  stat_re,stat_im);
#endif
          }

1074
1075
1076



1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
          for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) {
            if ((l2<2) || ((l2>(nsymb>>1) - 3)) ) {  // data symbols
              stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15)     - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15);
              stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15);
            } else { //reference_symbols
              stat_ref_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15)     - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
              stat_ref_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
            }

            off+=2;
1087
#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
1088
            printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l2,re,
1089
1090
1091
1092
1093
1094
1095
                  rxcomp[aa][off],rxcomp[aa][1+off],
                  cfo[l2<<1],cfo[1+(l2<<1)],
                  stat_re,stat_im);
#endif

          }

1096
#ifdef DEBUG_PUCCH_RX
knopp's avatar
knopp committed
1097
          printf("aa%d re %d : phase %d : stat %d\n",aa,re,phase,stat);
1098
#endif
1099
1100
1101
1102
1103

	  stat += ((((stat_re*stat_re)) + ((stat_im*stat_im)) +
		    ((stat_ref_re*stat_ref_re)) + ((stat_ref_im*stat_ref_im)))/nsymb);


1104
        } //re
1105
      } // aa
1106
1107

#ifdef DEBUG_PUCCH_RX
1108
      LOG_I(PHY,"Format 1A: phase %d : stat %d\n",phase,stat);
1109
#endif
1110
      if (stat>stat_max) {
1111
1112
        stat_max = stat;
        phase_max = phase;
1113
1114
      }
    } //phase
1115

1116
    stat_max/=(12);  //normalize to energy per symbol and RE
knopp's avatar
knopp committed
1117
1118
1119
#ifdef DEBUG_PUCCH_RX
    printf("[eNB] PUCCH fmt1a/b:  stat_max : %d, phase_max : %d\n",stat_max,phase_max);
#endif
1120
1121
1122

    stat_re=0;
    stat_im=0;
1123
    //    printf("PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH);
1124
    *Po_PUCCH = ((*Po_PUCCH>>1) + ((stat_max)>>1));
1125
    *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH/frame_parms->N_RB_UL) - eNB->rx_total_gain_dB;
knopp's avatar
knopp committed
1126
    *Po_PUCCH_update = 1;
1127
    /*
knopp's avatar
knopp committed
1128
1129
1130
1131
1132
1133
    printf("PUCCH1A : stat_max %d (%d,%d,%d) => Po_PUCCH %d\n",
	   dB_fixed(stat_max),
	   pucch1_thres+sigma2_dB,
	   pucch1_thres,
	   sigma2_dB,
	   dB_fixed(*Po_PUCCH));
1134
    */
1135
    // Do detection now
1136
1137
1138
    if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres))  {//


knopp's avatar
knopp committed
1139
1140
      *Po_PUCCH = ((*Po_PUCCH*1023) + stat_max)>>10;

1141
1142
      chL = (nsymb>>1)-4;

1143
1144
1145
1146
1147
1148