dlsch_scrambling.c 7.86 KB
Newer Older
1
2
3
4
5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 * 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
33
34
35
36
37
38
39
40
/*! \file PHY/LTE_TRANSPORT/dlsch_scrambling.c
* \brief Routines for the scrambling procedure of the PDSCH physical channel from 36-211, V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/

//#define DEBUG_SCRAMBLING 1

#include "PHY/defs.h"
#include "PHY/CODING/extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "defs.h"
#include "extern.h"
#include "PHY/extern.h"
41
42
#include "UTIL/LOG/vcd_signal_dumper.h"

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
static inline unsigned int lte_gold_scram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline));
static inline unsigned int lte_gold_scram(unsigned int *x1, unsigned int *x2, unsigned char reset)
{
  int n;

  if (reset) {
    *x1 = 1+ (1<<31);
    *x2=*x2 ^ ((*x2 ^ (*x2>>1) ^ (*x2>>2) ^ (*x2>>3))<<31);

    // skip first 50 double words (1600 bits)
    //      printf("n=0 : x1 %x, x2 %x\n",x1,x2);
    for (n=1; n<50; n++) {
      *x1 = (*x1>>1) ^ (*x1>>4);
      *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
      *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
      *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
    }
  }

  *x1 = (*x1>>1) ^ (*x1>>4);
  *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
  *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
  *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
  return(*x1^*x2);
  //  printf("n=%d : c %x\n",n,x1^x2);

}

71
void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
72
73
                      int mbsfn_flag,
                      LTE_eNB_DLSCH_t *dlsch,
74
		      int harq_pid,
75
76
                      int G,
                      uint8_t q,
77
		      uint16_t frame,
78
79
                      uint8_t Ns)
{
80

81
82
  int n;

gauthier's avatar
gauthier committed
83
84
  //  uint8_t reset;
  uint32_t x1, x2, s=0;
85
  uint8_t *dlsch_e=dlsch->harq_processes[harq_pid]->e;
knopp's avatar
knopp committed
86
  uint8_t *e=dlsch_e;
87

gauthier's avatar
gauthier committed
88
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_IN);
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#ifdef Rel14
  // Rule for accumulation of subframes for BL/CE UEs
  uint8_t Nacc=4;
  uint16_t j0,j,idelta;
  uint16_t i  = (Ns>>1) + (10*frame);
  uint16_t i0 = dlsch->i0;

  if (dlsch->sib1_br_flag==1)                              Nacc=1;
  else if (dlsch->rnti == 0xFFFF || dlsch->rnti == 0xFFFE) Nacc = (frame_parms->frame_type == TDD) ? 10 : 4;
  // Note: above SC-RNTI will also have to be added when/if implemented
  else if (dlsch->CEmode == CEmodeA)                       Nacc=1;
  else if (dlsch->CEmode == CEmodeB)                       Nacc = (frame_parms->frame_type == TDD) ? 10 : 4;

  if (frame_parms->frame_type == FDD || Nacc == 1) idelta = 0;
  else                                             idelta = Nacc-2;

  j0 = (i0+idelta)/Nacc;
  j  = (i - i0)/Nacc; 
#endif

110
111
112
  //  reset = 1;
  // x1 is set in lte_gold_generic
  if (mbsfn_flag == 0) {
113
114
115
116
117
118
119
120
121
#ifdef Rel14
    if (dlsch->i0 != 0xFFFF) {
      // rule for BL/CE UEs from Section 6.3.1 in 36.211
      x2=  (dlsch->rnti<<14) + (q<<13) + ((((j0+j)*Nacc)%10)<<9) + frame_parms->Nid_cell;
      if ((frame&1023) < 200) LOG_D(PHY,"Scrambling init for (i0 %d, i %d, j0 %d, j %d, Nacc %d) => x2 %d\n",i0,i,j0,j,Nacc,x2);
    }
    else
#endif
    x2 = (dlsch->rnti<<14) + (q<<13) + ((Ns>>1)<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1 for PDSCH
122
  } else {
123
    x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell_mbsfn; //this is c_init in 36.211 Sec 6.3.1 for PMCH
124
  }
125

126
#ifdef DEBUG_SCRAMBLING
127
  printf("scrambling: i0 %d rnti %x, q %d, Ns %d, Nid_cell %d, G %d x2 %x\n",dlsch->i0,dlsch->rnti,q,Ns,frame_parms->Nid_cell, G, x2);
128
#endif
129
  s = lte_gold_scram(&x1, &x2, 1);
130

131
  for (n=0; n<(1+(G>>5)); n++) {
132

133
#ifdef DEBUG_SCRAMBLING
knopp's avatar
knopp committed
134
    printf("scrambling %d : %d => ",k,e[k]);
135
#endif
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

                
    e[0] = (e[0]) ^ (s&1);      
    e[1] = (e[1]) ^ ((s>>1)&1);      
    e[2] = (e[2]) ^ ((s>>2)&1);      
    e[3] = (e[3]) ^ ((s>>3)&1);      
    e[4] = (e[4]) ^ ((s>>4)&1);      
    e[5] = (e[5]) ^ ((s>>5)&1);      
    e[6] = (e[6]) ^ ((s>>6)&1);      
    e[7] = (e[7]) ^ ((s>>7)&1);      
    e[8] = (e[8]) ^ ((s>>8)&1);      
    e[9] = (e[9]) ^ ((s>>9)&1);      
    e[10] = (e[10]) ^ ((s>>10)&1);      
    e[11] = (e[11]) ^ ((s>>11)&1);      
    e[12] = (e[12]) ^ ((s>>12)&1);      
    e[13] = (e[13]) ^ ((s>>13)&1);      
    e[14] = (e[14]) ^ ((s>>14)&1);      
    e[15] = (e[15]) ^ ((s>>15)&1);      
    e[16] = (e[16]) ^ ((s>>16)&1);      
    e[17] = (e[17]) ^ ((s>>17)&1);      
    e[18] = (e[18]) ^ ((s>>18)&1);      
    e[19] = (e[19]) ^ ((s>>19)&1);      
    e[20] = (e[20]) ^ ((s>>20)&1);      
    e[21] = (e[21]) ^ ((s>>21)&1);      
    e[22] = (e[22]) ^ ((s>>22)&1);      
    e[23] = (e[23]) ^ ((s>>23)&1);      
    e[24] = (e[24]) ^ ((s>>24)&1);      
    e[25] = (e[25]) ^ ((s>>25)&1);      
    e[26] = (e[26]) ^ ((s>>26)&1);      
    e[27] = (e[27]) ^ ((s>>27)&1);      
    e[28] = (e[28]) ^ ((s>>28)&1);      
    e[29] = (e[29]) ^ ((s>>29)&1);      
    e[30] = (e[30]) ^ ((s>>30)&1);      
    e[31] = (e[31]) ^ ((s>>31)&1);      
knopp's avatar
knopp committed
170
    
171
172
173
    // This is not faster for some unknown reason
    //    ((__m128i *)e)[0] = _mm_xor_si128(((__m128i *)e)[0],((__m128i *)scrambling_lut)[s&65535]);
    //    ((__m128i *)e)[1] = _mm_xor_si128(((__m128i *)e)[1],((__m128i *)scrambling_lut)[s>>16]);
174
#ifdef DEBUG_SCRAMBLING
knopp's avatar
knopp committed
175
    printf("%d\n",e[k]);
176
#endif
knopp's avatar
knopp committed
177
178
    
    
179
    s = lte_gold_scram(&x1, &x2, 0);
knopp's avatar
knopp committed
180
    e += 32;
181
182
  }

gauthier's avatar
gauthier committed
183
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_OUT);
184

185
186
187
}

void dlsch_unscrambling(LTE_DL_FRAME_PARMS *frame_parms,
188
189
190
191
192
193
194
                        int mbsfn_flag,
                        LTE_UE_DLSCH_t *dlsch,
                        int G,
                        int16_t* llr,
                        uint8_t q,
                        uint8_t Ns)
{
195
196

  int i,j,k=0;
gauthier's avatar
gauthier committed
197
198
  //  uint8_t reset;
  uint32_t x1, x2, s=0;
199

200
201
202
203
204
205
206
  //  reset = 1;
  // x1 is set in first call to lte_gold_generic

  if (mbsfn_flag == 0)
    x2 = (dlsch->rnti<<14) + (q<<13) + ((Ns>>1)<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1
  else
    x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell_mbsfn; //this is c_init in 36.211 Sec 6.3.1
207

208
#ifdef DEBUG_SCRAMBLING
209
    printf("unscrambling: rnti %x, q %d, Ns %d, Nid_cell %d G %d, x2 %x\n",dlsch->rnti,q,Ns,frame_parms->Nid_cell,G,x2);
210
#endif
211
  s = lte_gold_scram(&x1, &x2, 1);
212

213
  for (i=0; i<(1+(G>>5)); i++) {
214
    for (j=0; j<32; j++,k++) {
215
216
217
218
219
220
221
222
#ifdef DEBUG_SCRAMBLING
      printf("unscrambling %d : %d => ",k,llr[k]);
#endif
      llr[k] = ((2*((s>>j)&1))-1)*llr[k];
#ifdef DEBUG_SCRAMBLING
      printf("%d\n",llr[k]);
#endif
    }
223

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    s = lte_gold_scram(&x1, &x2, 0);
  }
}

void init_unscrambling_lut() {

  uint32_t s;
  int i=0,j;

  for (s=0;s<=65535;s++) {
    for (j=0;j<16;j++) {
      unscrambling_lut[i++] = (int16_t)((((s>>j)&1)<<1)-1);
    }
  }
}

void init_scrambling_lut() {

  uint32_t s;
  int i=0,j;

  for (s=0;s<=65535;s++) {
    for (j=0;j<16;j++) {
      scrambling_lut[i++] = (uint8_t)((s>>j)&1);
    }
249
  }
250
}